#javascript #arrays #object
#javascript #массивы #объект
Вопрос:
У меня есть объект, как вы можете видеть на картинке, когда я его console.log() , в первой строке он говорит, что course — это массив длиной 0. когда я разворачиваю его, он говорит, что длина равна 1, когда я делаю курс.длина говорит 0. Object.keys(курс).длина также указывает 0.
Что я делаю в своем приложении, так это то, что у меня есть listview. каждый элемент в listview можно расширять. каждый элемент является контейнером, и в каждом контейнере есть курсы. я получил контейнеры и курсы с удаленного сервера. все работало отлично. теперь я пытаюсь загрузить данные из локальной базы данных. это больше не работает…
Пожалуйста, посмотрите мой упрощенный код :
export default class Main extends Component{
constructor(props) {
super(props);
this.state = {
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
})
};
}
componentWillMount(){
this.fetchData();
}
fetchData(){
let data = fetch..... //// fetches data
let dsource = {};
for(let i=0; i < data.containers.length; i ){
let container = data.containers[i];
dsource[i] = {
containerId: containder.id,
course: [],
}
for(let x=0; x < container.courses.length; x ){
let course = container.courses[x];
dsource[i].course.push({
courseId: course.id,
courseName: course,name
});
}
}
this.setState({
dataSource: this.state.dataSource.cloneWithRows(dsource)
});
}
Я прочитал много вопросов по stackoverflow, много статей, но безуспешно:( Object.keys(Obj).length Obj.length все возвращает 0.
Некоторые говорят, потому что Obj.length будет показывать только перечислимые свойства. я попытался добавить перечислимые свойства к объекту с помощью Object.defineproperty, но без изменений.
какие-либо решения? любая помощь приветствуется.
Весь код (react native) :
"use strict";
import React, {Component, PropTypes} from 'react';
import {
ActivityIndicator,
ListView,
StyleSheet,
Text,
View,
Image,
NetInfo,
AlertIOS,
TouchableOpacity,
ScrollView,
Dimensions,
} from 'react-native';
let SQLite = require('react-native-sqlite-storage');
let Loading = require("./Loading");
let Accordion = require('react-native-accordion');
let DeviceInfo = require('react-native-device-info');
import Icon from 'react-native-vector-icons/Ionicons';
import { Actions } from 'react-native-router-flux';
import I18n from 'react-native-i18n';
import translations from './translations';
I18n.fallbacks = true;
let LOADING = {};
import CodePush from "react-native-code-push";
let { width, height } = Dimensions.get('window');
let db = SQLite.openDatabase({name : "oc.db", location: 'default'});
export default class Courses extends Component {
constructor(props) {
super(props);
this.state = {
isLoading: false,
dataSource: new ListView.DataSource({
rowHasChanged: (row1, row2) => row1 !== row2,
}),
isConnected: true,
dataLoaded: 0,
restartAllowed: true
};
}
toggleAllowRestart() {
this.state.restartAllowed
? CodePush.disallowRestart()
: CodePush.allowRestart();
this.setState({ restartAllowed: !this.state.restartAllowed });
}
sync() {
CodePush.sync(
{
installMode: CodePush.InstallMode.IMMEDIATE,
updateDialog: false
},
);
}
componentWillMount() {
NetInfo.isConnected.fetch().then(isConnected => {
this.setState({
isConnected: isConnected
});
});
NetInfo.isConnected.addEventListener(
'change',
isConnected => {
this.setState({
isConnected: isConnected
});
}
);
this.fetchData();
this.sync();
}
componentWillReceiveProps() {
this.fetchData();
this.setState({
keyForCourse: Date()
});
if(this.props.goto == 'register'){
Actions.register({type: 'reset'});
}
}
fetchData() {
console.log('Courses: fetchData running');
if(this.state.isConnected == 'wifi' || this.state.isConnected == 'cell' || this.state.isConnected == 'true' || this.state.isConnected){
this.setState({
isLoading: true,
});
db.transaction((tx) => {
tx.executeSql("SELECT * FROM users WHERE active=?",['yes'], (tx, results) => {
let len = results.rows.length;
let row = results.rows.item(0);
let userName = row.userName;
let userMail = row.userMail;
let userId = row.userId;
///// Getting courses list
db.transaction((tx) => {
tx.executeSql("SELECT * FROM containersC WHERE userId=?",[userId], (tx, results) => {
let dsource = {};
let len = results.rows.length;
if(len > 0){
for(let ind = 0; ind < len; ind ){
let cntr = results.rows.item(ind);
dsource[ind] = {
nid: cntr.nid,
title: cntr.title,
course: [],
courses: {},
};
//// Get courses for each container
db.transaction((tx) => {
tx.executeSql("SELECT * FROM courses WHERE userId=? AND container_nid=?",[userId, cntr.nid], (tx, results) => {
let lenc = results.rows.length;
if(lenc > 0){
for(var j=0; j < lenc; j ){
let crs = results.rows.item(j);
console.log('Course:', crs);
dsource[ind].course.push({
course_id: crs.course_id,
title: crs.title,
cost: crs.cost,
status: crs.status,
period: crs.period // .time_sys
});
dsource[ind].courses[j] = {
course_id: crs.course_id,
title: crs.title,
cost: crs.cost,
status: crs.status,
period: crs.period // .time_sys
};
}
dsource[ind].total = lenc;
}
}, function(){
console.log('Courses: Something went wrong Line 142');
});
});
//// End getting courses for containers
}
this.setState({
dataSource: this.state.dataSource.cloneWithRows(dsource),
isLoading: false,
dataLoaded: len
});
}
}, (err)=>{
console.log('Courses: Something went wrong', err);
});
}
);
//// End getting courses list
}, function(){
console.log('Courses: Unable to select users from database');
});
});
} else {
AlertIOS.alert(
I18n.t("no_connection_title"),
I18n.t("no_connection_desc")
);
}
}
selectRow(d, n) {
Actions.cdetails({cid: d, tit: n});
//Actions.rdetails({cid: d, tit: n});
}
renderRow(data) {
let header = (
<View style={{ backgroundColor: '#fff', margin: 7, marginBottom: 0 }}>
<View style={styles.rowContainer}>
<View style={styles.textContainer}>
<Icon name="ios-arrow-up" color="#00a2dd" size={30}></Icon>
<Text style={styles.title}>{data.title}</Text>
</View>
</View>
</View>
);
let headerOpen = (
<View style={{ backgroundColor: '#fff', margin: 7, marginBottom: 0 }}>
<View style={styles.rowContainer}>
<View style={styles.textContainer}>
<Icon name="ios-arrow-down" color="#00a2dd" size={30}></Icon>
<Text style={styles.title}>{data.title}</Text>
</View>
</View>
<View style={styles.separator}></View>
</View>
);
///////////
let cid = [];
let content = [];
let cll = data.total;
console.log('Data to render :', data);
console.log('Courses to render :', data.course);
for(let x=0; x < cll; x ){
cid[x] = data.course[x].course_id;
let courseCost;
switch(data.course[x].cost){
case 0:
courseCost = I18n.t("course_fee_free");
break;
case 1:
courseCost = data.course[x].cost;
break;
}
content.push(
<TouchableOpacity key={cid[x]} onPress={()=>{this.selectRow(data.course[x].course_id, data.course[x].title)}} >
<View style={[styles.cardContainer, {marginBottom: 5}, x == 0 ? { paddingTop: 6, } : {}, x == (cll 1) ? { marginBottom: 3} : {}]} key={cid[x]} >
<View style={styles.card}>
<View resizeMode="cover" style={styles.cardTitleContainer}>
<Text style={styles.cardTitle}>{data.course[x].title}</Text>
</View>
<View
style={{
padding : 15,
}}
>
<Text style={styles.cardContent}>
<Icon name="ios-calendar" color="#00a2dd" size={10}> {data.course[x].period}</Icon>{'n'}
<Icon name="ios-pricetag" color="#00a2dd" size={10}> {courseCost}</Icon>
</Text>
</View>
</View>
</View>
</TouchableOpacity>
);
}
let clist = (
<ScrollView style={styles.scrollView}>
<View style={{
padding: 6,
paddingBottom: 0,
borderTopColor: '#fff',
backgroundColor: '#fff',
margin: 7,
marginTop: 0,
}}>{content}</View>
</ScrollView>
);
////////////
return (
<Accordion
header={header}
headerOpen={headerOpen}
content={clist}
easing="easeOutCubic"
underlayColor="#ebebeb"
/>
);
}
render() {
let content= null;
if(this.state.isLoading){
content = <Loading/>;
} else {
if(this.state.dataLoaded < 1){
content = <View style={styles.errorContainer}>
<View style={styles.error}>
<Text style={styles.Errortext}>
{I18n.t("courses_no_course_available")}
</Text>
</View>
</View>;
} else {
content = <View style={{
flex: 1
}}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)}
/>
</View>;
}
}
return (
<View style={styles.container}>
{content}
</View>
);
}
}
let styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "white",
flexDirection: "column",
justifyContent: "center",
backgroundColor: '#e4e7ea',
},
separator: {
height: 1,
backgroundColor: "#d0d1d3",
},
scrollSpinner: {
marginVertical: 20,
},
cardContainer:{
flex: 1,
alignItems: 'stretch',
paddingLeft: 6,
paddingRight: 6,
borderColor: '#d0d1d3',
borderWidth: 1,
borderRadius: 5
},
card:{
flex: 1,
backgroundColor: '#ffffff',
borderRadius: 2,
borderColor: '#ffffff',
borderWidth: 1,
/*shadowColor: 'rgba(0, 0, 0, 0.12)',
shadowOpacity: 0.8,
shadowRadius: 2,
shadowOffset: {
height: 1,
width: 2,
},
*/
},
cardTitleContainer:{
flex: 1,
height: 35,
},
cardTitle:{
position: 'absolute',
top: 5,
left: 5,
backgroundColor: 'transparent',
padding: 10,
fontSize: 12,
color: '#4c4b4b',
fontWeight: 'bold',
},
rowContainer: {
flexDirection: 'column',
padding: 5,
},
textContainer: {
flexDirection: 'row',
flex: 1,
padding: 5
},
title: {
paddingTop: 7,
paddingLeft: 5,
color: '#00a2dd'
},
errorContainer: {
flex: 1,
flexDirection: "column",
backgroundColor: '#e4e7ea',
alignItems: 'center',
},
error: {
marginTop: 75,
width: width -150,
height: 100,
borderRadius: 15,
backgroundColor: '#ecebeb',
alignItems: 'center',
justifyContent: 'center',
},
Errortext: {
color: '#757575'
},
});
Courses = CodePush(Courses);
Комментарии:
1. Что вам явно нужно, покажите нам, что у вас не так в вашем коде?
2. Вы пробовали Object.keys(array) затем получить ключ по индексу? jsbin.com/huqojefiti/1/edit также поможет еще немного кода
3.
course
это массив длиной 1, а ваш объект находится в позиции 04. Я обновил вопрос целым кодом. пожалуйста, посмотрите на.
Ответ №1:
Есть 3 фактора, которые могут вызвать общее поведение, которое вы описываете. В вашем случае, я думаю, это первое:
-
При вызове
console.log(x)
консоль Chrome покажет сводную информацию об объектеx
в данный момент. Однако, когда вы разворачиваете объект, значение получается снова. Подробный объект, который вы видите, возможно, изменился с момента вызоваconsole.log()
, и изменения появятся в деталях. -
Свойства могут принадлежать прототипу объекта (в отличие от «собственных» свойств):
> x = {a:1} { a: 1 } > y = Object.create(x) > y.a 1 > y {} > Object.keys(y) []
-
Свойства могут быть неисчислимыми и не будут отображаться в списках ключей.
length
является неисчислимым свойством.
Комментарии:
1. таким образом, возможно, что мой код не выполняется, следовательно, и перед его извлечением и помещением всех данных в массив, он пытается показать содержимое и его длину. верно? я попытаюсь использовать async / await, чтобы посмотреть, что произойдет. спасибо за ваш ответ
Ответ №2:
Попробуйте это,
const keys =[];
const person = {
name : 'Jobelle',
age :22,
mob :8547391599
}
Object.getOwnPropertyNames(tempObj).forEach(prop => {
keys.push(prop);
});
Ответ №3:
Как вы сказали, Object.keys относится к перечислимым свойствам. Свойство «длина» массива (который также является объектом) просто не поддается перечислению.
Комментарии:
1. Итак, что вы предлагаете? как я могу узнать, сколько элементов находится внутри массива или объекта?
2. Я не думаю, что OP регистрирует массив, хотя его формулировку можно понять таким образом. Регистрируется объект, свойство которого
course
показывает пустой массив, но при использовании показывает полный массив. Примечание : downvote не от меня.3. Прежде всего, объясните свои отрицательные голоса, чтобы мы все могли учиться! Может быть, я просто что-то неправильно понял в отношении вопроса, но то, что я сказал, в целом правильно. @Ataomega: Используется
length
для определения количества элементов в массиве . ИспользуетсяObject.keys
для определения количества (перечислимых) свойств в объекте . По крайней мере, так я это делаю.4. @frontend_dev спасибо за ваш комментарий. поскольку длина возвращала ноль, я попробовал Object.keys().length , который также вернул ноль
5. @frontend_dev во время тестирования я попробовал оба варианта. я добавил один курс и курсы, один массив и другой один объект. попробовал длину и Object.keys. длина для обоих из них, ни одна не работает должным образом.