变量声命周期
垃圾回收
- 找出不再使用的变量
- 释放其占用内存
- 固定的时间间隔运行
- 解除由于闭包产生的对fn AO的引用
标记清除
- 排除全局变量、排除闭包引用的AO中的变量
- 进入环境 → 离开环境
- 常用
引用计数
- 引用计数为0时清除
- 对循环引用的情况,如果不手动接触引用(a = null),则无法清除
arguments
属性
- 函数内部对应参数值的实参列表
- 类数组对象 Array-like
- 有属性callee,指向它的宿主函数
- 属性Symbol(Symbol.iterator) 表示可迭代
- constructor是Object
- 有length属性
- 属性下标从0开始
- 没有数组的内置方法
- 注意:箭头函数没有arguments
function test(a, b) {console.log(arguments) // 1 2 3console.log(Object.prototype.toString.call(arguments)) // [object Arguments]console.log(Array.isArray(arguments)) // false
}
test(1, 2, 3,)
普通对象是不可迭代的
- 三个参数,迭代到第四个便完成了
function* generator(args) {for (var key in args) {yield key}
}
var it = generator(obj)
console.log(it.next())
console.log(it.next())
console.log(it.next())
console.log(it.next())
function test(a, b) {var it = generator(arguments)console.log(it.next())console.log(it.next())console.log(it.next())console.log(it.next())
}
test(1, 2, 3)
箭头函数内使用实参(es6弱化了arguments)
- 严格模式让arguments和eval少了一些奇怪的行为。两者在通常的代码中都包含了很多奇怪的行为。
Strict mode makes arguments and eval less bizarrely magical. Both involve a considerable amount of magical behavior in normal code.
arguments的一些操作会阻止js引擎的优化
对参数使用slice会阻止某些JavaScript引擎中的优化 (比如 V8 - 更多信息)。如果你关心性能,尝试通过遍历arguments对象来构造一个新的数组。另一种方法是使用被忽视的Array构造函数作为一个函数
var args = (arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments));
bluebird-petkaantonov
- 多种方式将arguments转为新数组返回
function test() {var arr = []for (var v of arguments) {arr.push(v)}// return arr// return arguments.length === 1 ? [arguments[0]] : Array.from(arguments)return arguments.length === 1 ? [arguments[0]] : Array.apply(null, arguments)
}
console.log(test(1, 2, 3))
使用场景:
- 实参个数 > 形参个数
- 不定参数
形、实参的对应关系
Note: If you’re writing ES6 compatible code, then rest parameters should be preferred.
Note: “Array-like” means that arguments has a length property and properties indexed from zero, but it doesn’t have Array’s built-in methods like forEach() and map(). See §Description for details.
当非严格模式中的函数没有包含剩余参数、默认参数和解构赋值,那么arguments对象中的值会跟踪参数的值(反之亦然)。
1. 形参中但凡有一个有默认值, 形、实参不再对应
function test(a = 100, b, c) {arguments[1] = 1000console.log(b, arguments[1]) // 2 100
}
test(1, 2, 3)
不统一的具体表现
1. ES6形参默认值
- 当实参为undefined时,形参若有默认值,便取默认值
function test(a = 100, b, c) {arguments[0] = 1000console.log(a, arguments[0]) // 100 1000
}
test()
- 形参、实参并不统一
function test(a = 100, b, c) {console.log(a, arguments[0]) // 100 undefined
}
test()
- 修改形参,便不再取默认值
function test(a = 100, b, c) {a = 666console.log(a, arguments[0]) // 666 1
}
test(1)
2. ES6使用展开运算符
function test(...args) {arguments[0] = 100console.log(args[0], arguments[0]) // 1 100
}
test(1)
3. ES6参数解构
function test({ a, b, c }) {arguments[0]['a'] = 100console.log(a, arguments[0]['a']) // 1 100
}
test({ a: 1, b: 2, c: 3 })
MDN: 注意: 在严格模式下,arguments对象已与过往不同。arguments[@@iterator]不再与函数的实际形参之间共享,同时caller属性也被移除。
4*. 严格模式下,怎么都不对应
function test(a, b, c) {'use strict'arguments[0] = 100console.log(a, arguments[0]) // 1 100
}
test(1)
5. ES5实参undefined
var test = function (a, b) {a = 1console.log(a, arguments[0]) // 1 undefined
}
test()
// 这个相当于es5无默认值
var test = function (a = undefined, b) {console.log(a, arguments[0]) // 100 100
}
test(100)
arguments