首先是经典的 for i 循环,它使你可以遍历数组或可索引的且有 length 属性的任何对象。...这包括原型链中父对象的属性,以及被分配为方法的所以属性。换句话说,它遍历了一些人们可能想不到的东西。使用 for ... in 通常意味着循环块中有很多保护子句,以避免出现不需要的属性。...一个普通的 javascript 对象是不可迭代的。...如果你执行下面这段代码: // 无法正常执行 const foo = { 'apples':'oranges', 'pears':'prunes' } for(const [key, value...@@ 表示法有点误导性,我们真正 要做的是用预定义的 Symbol.iterator 符号定义方法。
关于这一点的棘手之处在于,可迭代对象的迭代器方法没有传统的名称,而是使用符号Symbol.iterator作为其名称。...要使类可迭代,必须实现一个方法,其名称为符号Symbol.iterator。该方法必须返回具有next()方法的迭代器对象。...如果一个属性不可配置,你就无法改变它的可配置或可枚举属性。 如果一个访问器属性不可配置,你就无法更改其 getter 或 setter 方法,也无法将其更改为数据属性。...如果一个数据属性不可配置,你就无法将其更改为访问器属性。 如果一个数据属性不可配置,你就无法将其可写属性从false更改为true,但你可以将其从true更改为false。...当代码尝试从对象中读取值时,这些读取会正常转发到目标对象。但如果任何代码尝试修改对象或其属性,处理程序对象的方法会抛出 TypeError。
相反,是通过调用 range[Symbol.iterator]() 创建了另一个对象,即所谓的“迭代器”对象,并且它的 next 会为迭代生成值。...技术上来说,可迭代对象必须实现 Symbol.iterator 方法。 obj[Symbol.iterator]() 的结果被称为 迭代器(iterator)。由它处理进一步的迭代过程。...Symbol.iterator 方法会被 for..of 自动调用,但我们也可以直接调用它。 内置的可迭代对象例如字符串和数组,都实现了 Symbol.iterator。...字符串迭代器能够识别代理对(surrogate pair)。(译注:代理对也就是 UTF-16 扩展字符。) 有索引属性和 length 属性的对象被称为 类数组对象。...跟 Set 一样,WeakSet 支持 add,has 和 delete 方法,但不支持 size 和 keys(),并且不可迭代。
push、pop、shift、unshift push/pop 方法运行的比较快,而 shift/unshift 比较慢。 这个有点像是堆栈,push和pop都是操作栈顶的元素,所以快。...技术上来说,可迭代对象必须实现 Symbol.iterator 方法。 obj[Symbol.iterator]() 的结果被称为 迭代器(iterator)。由它处理进一步的迭代过程。...Symbol.iterator 方法会被 for..of 自动调用,但我们也可以直接调用它。 内置的可迭代对象例如字符串和数组,都实现了 Symbol.iterator。...字符串迭代器能够识别代理对(surrogate pair)。(译注:代理对也就是 UTF-16 扩展字符。) 有索引属性和 length 属性的对象被称为 类数组对象。...跟 Set 一样,WeakSet 支持 add,has 和 delete 方法,但不支持 size 和 keys(),并且不可迭代。
在map出现之前,我们使用的是对象的方式来存储键值对,键是属性名,值是属性值。键值对数据结合的特点就是:键不可重复。...如果用对象来存储键值对在某些场景下不太如意: 键名只能是字符串或者符号,这就给它的使用带来很大的限制 获取数据的数量不方便,如果想知道对象中存了多少个数据,就必须先拿到所有的键名,然后通过求数组的长度才能知道对象中有多少个属性...(item); //取出第一个迭代值和第二个迭代值 const iterator = item[Symbol.iterator]();...== "function") { throw new TypeError(`${typeof target} ${target} is not is not iterable (..._datas.push({ key, value }) } } //delete
迭代过程 迭代的过程如下: 通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了...value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束 当 done 为 true 时则遍历结束 下面通过一个简单的例子进行说明: const items...方法创建一个迭代器,之后不断地调用 next 方法对数组内部项进行访问,当属性 done 为 true 时访问结束。...普通对象是由 object 创建的,不可迭代: // TypeError for (let item of {}) { console.log(item); } // Uncaught...of 操作数必须是可迭代,这意味着如果是普通对象则无法进行迭代。
Symbol出现之前,我们会经常遇到多个不相同的库操作的DOM属性相同,导致第三方库无法正常运行。Symbol解决了“对象属性名都是字符串、数字,这容易造成属性名的冲突”的问题。...var s1 = Symbol.for("foo"); Symbol.keyFor(s1) // "foo" 常用Symbol值 (1)Symbol.iterator @@iterator用于为对象定义一个方法并返回一个属于所对应对象的迭代器...,该迭代器会被for-of语句使用。...(注意,ES5无法模拟该特性)。 元编程重点在于:在一个程序的内容、运行环境、配置等都不做任何修改的情况下,可以通过其他程序对其进行读取或修改。...比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回
迭代过程 迭代的过程如下: 通过 Symbol.iterator 创建一个迭代器,指向当前数据结构的起始位置 随后通过 next 方法进行向下迭代指向下一个位置, next 方法会返回当前位置的对象,对象包含了...value 和 done 两个属性, value 是当前属性的值, done 用于判断是否遍历结束 当 done 为 true 时则遍历结束 下面通过一个简单的例子进行说明: const items...方法创建一个迭代器,之后不断的调用 next 方法对数组内部项进行访问,当属性 done 为 true 时访问结束。...普通对象是由 object 创建的,不可迭代: // TypeError for (let item of {}) { console.log(item); } for...of循环 for...of 操作数必须是可迭代,这意味着如果是普通对象则无法进行迭代。
为了变成可迭代对象,一个对象必须实现@@iterator方法,意思是这个对象(或者它原型链prototype chain上的某个对象)必须有一个名字是Symbol.iterator的属性: 属性 值 [...Symbol.iterator] 返回一个对象的无参函数,被返回对象符合迭代器协议 当一个对象需要被迭代的时候(比如开始用于一个for...of循环中),它的@@iterator方法被调用并且无参数,...当一个对象被认为是一个迭代器时,它实现了一个next()的方法并且拥有以下含义: 属性 值 next 返回一个对象的无参函数,被返回对象拥有两个属性: 1. done(boolean) - 如果迭代器已经经过了被迭代序列时为...这时value可能描述了该迭代器的返回值 - 如果迭代器可以产生序列中的下一个值,则为false。这等效于连同done属性也不指定。 2. value - 迭代器返回的任何JavaScript值。...使用可迭代协议和迭代器协议的例子: var str = 'hello'; // 可迭代协议使用for...of访问 typeof str[Symbol.iterator]; // 'function
: Cannot redefine property: a 不管是不是处于严格模式,尝试修改一个不可配置的属性描述符都会出错,即把configurable修改成false是单向操作,无法撤销。...b会静默失败;在严格模式下,将会抛出TypeError错误。...这个方法是应用在对象上的级别最高的不可变性,它会禁止对对象本身以及任意直接属性的修改(这个对象引用的其他对象不受影响)。...如果是,在非严格模式下静默失败,在严格模式下抛出TypeError异常; 3)如果都不是,将该值设置为属性的值。 如果对象中不存在这个属性,[[Put]]操作会更复杂。...undefined, done: true} //用for...of遍历myObject for(var v of myObject){ console.log(v);//2 3 } 我们把符号当作可计算属性名
如果无法转换,则抛出错误 # 定型数组 定型数组是另一种形式的ArrayBuffer视图。...创建定型数组的方式包括读取已有的缓冲、使用自有缓冲、填充可迭代结构,以及填充基于任意类型的定型数组。...符号属性,因此可以通过for..of循环和扩展操作符来操作 # 合并、复制和修改定型数组 定型数组同样使用数组缓冲来存储数据,而数组缓冲无法调整大小,故以下方法不适用于定型数组 concat() pop...Set会维护值插入时的顺序,因此支持按顺序迭代 集合实例提供一个迭代器,能以插入顺序生成集合内容,可以通过values()及其别名方法keys()(或者Symbol.iterator属性)取得这个迭代器...removeReference() { container.val = null; } // 执行removeReference()后会摧毁值对象的最后一个引用,垃圾回收程序就可以把这个值清理掉 # 不可迭代值
一、Iterator(遍历器)的存在 1、迭代器模式 迭代器模式是指提供一种方法顺序访问一个聚合对象中的各个元素,而又不需要暴露该对象的内部表示。...在使用迭代器模式之后,即使不关心对象的内部构造,也可以按顺序访问其中的每个元素。...以上数据类型,都有 Symbol.iterator 属性,属性值是一个函数,执行这个函数就会返回一个迭代器。这个迭代器就有 next 方法可顺序迭代子元素。...1 } // Uncaught TypeError: Result of the Symbol.iterator method is not an object // 翻译:Symbol.iterator...var obj2 = {}; obj2[Symbol.iterator] = function () { return {name: 'webchang'} } // Uncaught TypeError
但是,如果你这样做了 —— for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not...iterable 你将得到一个类型错误,说明该对象不可迭代。...但是,ECMA 没有使用名称 iteratorMethod,而是使用名称 Symbol.iterator。 Symbols 提供的名称是唯一的,不能与其他属性名称冲突。...同时,Symbol.iterator 返回一个名为迭代器的对象,这个迭代器将拥有一个名为next的方法,该方法将返回一个具有键值为 value 和 done 的对象。...== true; nextValue = iterator.next()) { newArray.push(nextValue.value); } newArray.push(2) newArray.push
但是,如果你这样做了 —— for (let author of myFavouriteAuthors) { console.log(author) } // TypeError: {} is not...iterable 你将得到一个类型错误,说明该对象不可迭代。...但是,ECMA没有使用名称 iteratorMethod,而是使用名称 Symbol.iterator。Symbols 提供的名称是唯一的,不能与其他属性名称冲突。...同时,Symbol.iterator 返回一个名为迭代器的对象,这个迭代器将拥有一个名为next的方法,该方法将返回一个具有键值为 value 和 done 的对象。...== true; nextValue = iterator.next()) { newArray.push(nextValue.value); } newArray.push(2) newArray.push
{i}: v-${v}, array-[${array}]`);});// index 0: v-1, array-[1,,,4]// index 3: v-4, array-[1,,,4] 5、 不可中断...: forEach一旦执行, 一般情况下无法停止, 除非是中途抛出异常, 然后捕获(() => { [1, 2, 3].forEach((v, i, array) => { console.log...Symbol属性自身属性原型属性不可枚举属性for...in否是是否Object.keys否是否否Object.getOwnPropertyNames否是否是 4、 遍历过程中可以使用return、break...(variable of iterable) { /* ... */}特点 1、 必须为可迭代对象, 可以使用 typeof obj[Symbol.iterator] === ‘function...’ 来进行迭代对象判断, 如果为非迭代对象, 会直接报错for (const v of { a: 1 }) { console.log(v);}// TypeError: {(intermediate
console.log(a); // 3 } console.log(a); // 2 # const 声明的常量类似于指针,它指向某个引用,并非一成不变 { const Arr = [5,6]; Arr.push...,那么这个属性会是不可枚举的 var o = { val: 10, [ Symbol("random") ]: "I'm a symbol", }; console.log(Object.getOwnPropertyNames...(o)); // val 获取对象 symbol 属性,需要使用 Object.getOwnPropertySymbols(o) # 迭代器(Iterators) 迭代器允许每次访问数据集合的一个元素,...ES6 中可以通过 Symbol.iterator 给对象设置默认的遍历器,无论什么时候对象需要被遍历,执行它的 @@iterator 方法便可以返回一个用于获取值的迭代器。...数组默认就是一个迭代器 var arr = [11,12,13]; var itr = arr[Symbol.iterator](); itr.next(); // { value: 11, done
不能使用箭头函数来创建生成器;ES6函数的简写方式可以(只需在函数名前加星号) 可迭代对象具有Symbol.iterator属性,ES6中,所有的集合对象(数组、Set集合和Map集合)和字符串都是可迭代对象...,这些对象都具有默认迭代器; let collection = { items: [], *[Symbol.iterator]() { for (let item of...this.items) { yield item } } } collection.items.push(1) collection.items.push...,通过迭代器从对象中读取相应的值并插入到一个数组中。...(key in receiver)) { throw new TypeError(`属性${key}不存在`) } return Reflect.get
function foo() { return Promise.resolve().then(foo); }; 每次调用'foo'都会继续在微任务队列上添加另一个'foo'回调,因此事件循环无法继续处理其他事件...6、我们能否以某种方式为下面的语句使用展开运算而不导致类型错误 var obj = { x: 1, y: 2, z: 3 }; [...obj]; // TypeError 答案:会导致TypeError...Array 或Map 是具有默认迭代行为的内置迭代器。对象不是可迭代的,但是可以通过使用iterable和iterator协议使它们可迭代。...在Mozilla文档中,如果一个对象实现了@@iterator方法,那么它就是可迭代的,这意味着这个对象(或者它原型链上的一个对象)必须有一个带有@@iterator键的属性,这个键可以通过常量Symbol.iterator...var obj = { a: 1, b: 2 }; //a,b 都是 enumerables 属性 // 将{c:3}设置为'obj'的原型,并且我们知道 // for-in 循环也迭代 obj 继承的属性
然后是 NodeJS 的一些实现 额外需要注意的是: JS 原生是单线程, 但是一些 underlying platform (Browser and NodeJS)....with transaction } Strings implementing @@iterator [Symbol.iterator] 其实是个普遍存在的属性, Array/Map/Set 以及...String 都有这个属性 "Joy of JavaScript"[Symbol.iterator]; // [Function: [Symbol.iterator]] for(const letter...['push'] === 'function' && typeof obj[Symbol.iterator] === 'function'; } const reactivize = (obj...) => { implementsPush(obj) || new TypeError("Object does not implement a push protocol"); const
function foo() { return Promise.resolve().then(foo); }; 每次调用' foo'都会继续在微任务队列上添加另一个' foo'回调,因此事件循环无法继续处理其他事件...---- 问题6 : 会导致TypeError错误 解析: 展开语法 和 for-of 语句遍历 iterable对象定义要遍历的数据。 Array 或 Map 是具有默认迭代行为的内置迭代器。...对象不是可迭代的,但是可以通过使用iterable和iterator协议使它们可迭代。...在Mozilla文档中,如果一个对象实现了 @@iterator方法,那么它就是可迭代的,这意味着这个对象(或者它原型链上的一个对象)必须有一个带有 @@iterator键的属性,这个键可以通过常量 Symbol.iterator...var obj = { a: 1, b: 2 }; //a,b 都是 enumerables 属性 // 将{c:3}设置为'obj'的原型,并且我们知道 // for-in 循环也迭代 obj 继承的属性
领取专属 10元无门槛券
手把手带您无忧上云