Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/qt/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为什么对象在JavaScript中不可编辑?_Javascript_Arrays_Iterator_Ecmascript 6_Ecmascript 5 - Fatal编程技术网

为什么对象在JavaScript中不可编辑?

为什么对象在JavaScript中不可编辑?,javascript,arrays,iterator,ecmascript-6,ecmascript-5,Javascript,Arrays,Iterator,Ecmascript 6,Ecmascript 5,为什么默认情况下对象不可编辑 我一直看到与迭代对象相关的问题,常见的解决方案是迭代对象的属性并以这种方式访问对象中的值。这似乎很常见,让我想知道为什么对象本身不可移植。 默认情况下,像ES6这样的语句很适合用于对象。由于这些功能仅适用于不包括{}对象的特殊“iterable对象”,因此我们必须对我们想要使用它的对象进行调整 for…of语句创建了一个循环,循环遍历iterable对象 (包括数组、映射、集合、参数对象等) 例如,使用ES6: 以上内容按照我在Firefox中运行代码时希望的顺序正

为什么默认情况下对象不可编辑

我一直看到与迭代对象相关的问题,常见的解决方案是迭代对象的属性并以这种方式访问对象中的值。这似乎很常见,让我想知道为什么对象本身不可移植。

默认情况下,像ES6这样的语句很适合用于对象。由于这些功能仅适用于不包括
{}
对象的特殊“iterable对象”,因此我们必须对我们想要使用它的对象进行调整

for…of语句创建了一个循环,循环遍历iterable对象 (包括数组、映射、集合、参数对象等)

例如,使用ES6:

以上内容按照我在Firefox中运行代码时希望的顺序正确记录数据(Firefox支持):

默认情况下,
{}
对象是不可编辑的,但为什么?可移植对象的缺点是否会超过其潜在好处?与此相关的问题有哪些?

此外,由于
{}
对象不同于“类似数组”的集合和“iterable对象”,例如和,因此它们不能转换为数组

例如:

var argumentsArray=Array.prototype.slice.call(参数)

或与数组方法一起使用:

Array.prototype.forEach.call(节点列表,函数(元素){})

除了我上面提到的问题之外,我还想看到一个关于如何将
{}
对象转换为iterables的工作示例,特别是那些提到
[Symbol.iterator]
的人,这应该允许这些新的
{}
“iterable对象”使用类似
的语句来表示
of
。另外,我想知道使对象可移植是否允许将它们转换为数组

我尝试了下面的代码,但是我得到了一个
TypeError:无法将未定义的转换为object

var example = {a: {e: 'one', f: 'two'}, b: {g: 'three'}, c: {h: 'four', i: 'five'}};

// I want to be able to use "for...of" for the "example" object.
// I also want to be able to convert the "example" object into an Array.
example[Symbol.iterator] = function* (obj) {
   for (let key of Object.keys(obj)) {
     yield [key, obj[key]];
   }
};

for (let [key, value] of example) { console.log(value); } // error
console.log([...example]); // error

我想问题应该是“为什么没有内置的对象迭代

向对象本身添加可写性可能会产生意想不到的后果,不,没有办法保证顺序,但编写迭代器非常简单

function* iterate_object(o) {
    var keys = Object.keys(o);
    for (var i=0; i<keys.length; i++) {
        yield [keys[i], o[keys[i]]];
    }
}

我将尝试一下。请注意,我与ECMA没有关联,也无法了解他们的决策过程,因此我无法确定他们为什么做了或没有做任何事情。不过,我将陈述我的假设,并尽我所能

1.为什么首先要为
构造的…添加一个

JavaScript已经在
结构中包含了一个
for…,它可以用来迭代对象的属性。但是,它非常有用,因为它枚举了对象上的所有属性,并且往往只在简单的情况下工作

它在更复杂的情况下会崩溃(包括在数组中,在数组中,它的使用往往是通过正确使用数组所需的保护措施来实现的)。您可以通过使用
hasOwnProperty
(除其他外)来解决这一问题,但这有点笨拙和不雅观

因此,我的假设是,正在添加
for…of
构造,以解决与
for…in
构造相关的缺陷,并在迭代时提供更大的实用性和灵活性。人们倾向于将
for…in
视为一个
forEach
循环,通常可应用于任何收集并在任何可能的上下文中生成合理的结果,但事实并非如此。循环的
for…修复了这一问题

我还假设现有ES5代码在ES6下运行并产生与在ES5下相同的结果是很重要的,因此不能对
结构中的
for…的行为进行破坏性更改

2.
for…of
如何工作?

对于这部分很有用。具体来说,如果对象定义了
符号.iterator
属性,则将其视为
iterable

属性定义应该是一个函数,它返回集合中的项,one、by、one,并设置一个标志,指示是否有更多的项要获取。提供了预定义的实现,并且相对清楚的是,使用
for…of
只会委托迭代器函数

这种方法很有用,因为它使提供自己的迭代器变得非常简单。我可能会说,这种方法可能会带来实际问题,因为它依赖于定义一个以前不存在的属性,但我可以告诉你,情况并非如此,因为除非你仔细考虑,否则新属性基本上会被忽略你可以去寻找它(也就是说,它不会作为一个键出现在
循环中,等等)。所以情况并非如此

撇开实际的非问题不谈,从概念上讲,用一个新的预定义属性开始所有对象,或者含蓄地说“每个对象都是一个集合”,可能会被认为是有争议的

3.为什么对象在默认情况下不可
iterable
使用
for…of

我猜这是以下因素的组合:

  • 默认情况下,将所有对象设置为可伸缩的
  • ,可能被认为是不可接受的,因为它添加了以前没有的属性,或者因为对象(不一定)是集合。正如Felix所指出的,“对函数或正则表达式对象进行迭代意味着什么?”
  • 简单对象已经可以在
  • 中使用
    对…进行迭代,并且不清楚内置迭代器实现与现有的
    对中的行为有什么不同/更好的地方。因此,即使#1是错误的,并且添加属性是可以接受的,也可能不会
    function* iterate_object(o) {
        var keys = Object.keys(o);
        for (var i=0; i<keys.length; i++) {
            yield [keys[i], o[keys[i]]];
        }
    }
    
    for (var [key, val] of iterate_object({a: 1, b: 2})) {
        console.log(key, val);
    }
    
    a 1
    b 2
    
    var myIterable = {};
    myIterable[Symbol.iterator] = function* () {
        yield 1;
        yield 2;
        yield 3;
    };
    
    for (var value of myIterable) {
        console.log(value);
    }
    
    for (let levelOneKey in object) {
        console.log(levelOneKey);         //  "example"
        console.log(object[levelOneKey]); // {"random":"nest","another":"thing"}
    
        var levelTwoObj = object[levelOneKey];
        for (let levelTwoKey in levelTwoObj ) {
            console.log(levelTwoKey);   // "random"
            console.log(levelTwoObj[levelTwoKey]); // "nest"
        }
    }
    
    obj = { 
        a: '1', 
        b: { something: 'else' }, 
        c: 4, 
        d: { nested: { nestedAgain: true }}
    };
    
    obj[Symbol.iterator] = function() {
        var keys = [];
        var ref = this;
        for (var key in this) {
            //note:  can do hasOwnProperty() here, etc.
            keys.push(key);
        }
    
        return {
            next: function() {
                if (this._keys && this._obj && this._index < this._keys.length) {
                    var key = this._keys[this._index];
                    this._index++;
                    return { key: key, value: this._obj[key], done: false };
                } else {
                    return { done: true };
                }
            },
            _index: 0,
            _keys: keys,
            _obj: ref
        };
    };
    
    var array = [...myIterable];
    
    var files = {
        '/root': {type: 'directory'},
        '/root/example.txt': {type: 'file'}
    };
    
    for (let [key, {type}] of Object.entries(files)) {
        console.log(type);
    }
    
    Object.prototype[Symbol.iterator] = function * () {
        for (const [key, value] of Object.entries(this)) {
            yield {key, value}; // or [key, value]
        }
    };
    
    for (const {key, value:{type}} of files) {
        console.log(key, type);
    }
    
    for (const {key, value:item1} of example) {
        console.log(key);
        console.log(item1);
        for (const {key, value:item2} of item1) {
            console.log(key);
            console.log(item2);
        }
    }
    
    Object.defineProperty(Object.prototype, Symbol.iterator, {
        enumerable: false,
        value: function * (){
            for(let key in this){
                if(this.hasOwnProperty(key)){
                    yield [key, this[key]];
                }
            }
        }
    });
    
    var iterableProperties={
        enumerable: false,
        value: function * () {
            for(let key in this) if(this.hasOwnProperty(key)) yield this[key];
        }
    };
    
    var fruit={
        'a': 'apple',
        'b': 'banana',
        'c': 'cherry'
    };
    Object.defineProperty(fruit,Symbol.iterator,iterableProperties);
    for(let v of fruit) console.log(v);
    
    var instruments={
        'a': 'accordion',
        'b': 'banjo',
        'c': 'cor anglais'
    };
    Object.defineProperty(instruments,Symbol.iterator,iterableProperties);
    for(let v of instruments) console.log(v);