【问题标题】:Javascript: Object have keys, but Object.keys returns emptyJavascript:对象有键,但 Object.keys 返回空
【发布时间】:2017-02-20 04:58:37
【问题描述】:

我有一个对象,正如你在图片中看到的那样,当我使用 console.log() 时,在第一行它说 course 是一个长度为 0 的数组。当我展开它时,它说长度为 1,当我做 course.length 时它说 0。Object.keys(course).length 也说 0。

我在我的应用程序中所做的是,我有一个列表视图。 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 向对象添加可枚举属性,但没有更改。

有什么解决办法吗?非常感谢任何帮助。

整个代码(反应原生):

"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);

【问题讨论】:

  • 您显然需要什么,向我们展示您的代码有什么问题?
  • 您是否尝试过 Object.keys(array) 然后通过索引获取密钥? jsbin.com/huqojefiti/1/edit 还有一些代码会有所帮助
  • course 是一个长度为 1 的数组,您的对象位于位置 0
  • 我已经用整个代码更新了这个问题。请掠夺一下。

标签: javascript arrays object


【解决方案1】:

如您所说,Object.keys 指的是 可枚举 属性。数组(也是一个对象)的“长度”属性是不可枚举的。

【讨论】:

  • 那你有什么建议?我怎么知道数组或对象中有多少项?
  • 我不认为 OP 正在记录一个数组,尽管他的措辞可以这样理解。记录的是一个对象,其属性course 显示一个空数组,但在消耗时显示一个完整数组。 注意:downvote 不是来自我。
  • 首先说明你的反对意见,让大家学习!也许我只是对这个问题理解不正确,但我所说的总体上是正确的。 @Ataomega:使用length 来确定array 中的项目数。使用Object.keys 确定object 中(可枚举)属性的数量。至少我是这样做的。
  • @frontend_dev 感谢您的评论。由于长度返回零,我尝试了 Object.keys().length ,它也返回零
  • @frontend_dev 在我测试时,我都尝试了。我添加了一门课程和课程,一个数组和另一个对象。尝试了它们的长度和 Object.keys.length,没有一个按预期工作。
【解决方案2】:

有 3 个因素会导致您描述的一般行为。在你的情况下,我认为这是第一个:

  1. 当您调用console.log(x) 时,Chrome 控制台将显示当时对象x 的摘要。但是,当您展开对象时,会再次获得该值。您看到的详细对象可能在调用 console.log() 后发生了变化,变化将出现在详细信息中

  2. 属性可能属于对象的原型(与“自己的”属性相反):

    > x = {a:1}
    { a: 1 }
    > y = Object.create(x)
    > y.a
    1
    > y
    {}
    > Object.keys(y)
    []
    
  3. 属性可能是不可枚举的,并且不会显示在关键列表中。 length 是不可枚举的属性。

【讨论】:

  • 所以我的代码可能没有运行,因此在它获取并将所有数据放入 array 之前,它试图显示内容和它的长度。正确的?我会尝试使用 async / await 看看会发生什么。谢谢你的回答
【解决方案3】:

试试这个,

 const keys =[];  
    const person = {
    name : 'Jobelle',
    age :22,
    mob :8547391599
    }
    
    Object.getOwnPropertyNames(tempObj).forEach(prop => {
              keys.push(prop);
            });

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-08-18
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 2021-07-14
    • 2011-10-02
    • 1970-01-01
    相关资源
    最近更新 更多