變量聲命周期
垃圾回收
- 找出不再使用的變量
- 釋放其占用內存
- 固定的時間間隔運行
- 解除由于閉包產生的對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