原文出處
JavaScript深入之類數(shù)組對象與arguments
類數(shù)組對象
所謂的類數(shù)組對象:
擁有一個 length 屬性和若干索引屬性的對象
舉個例子:
var array = ['name', 'age', 'sex'];
var arrayLike = {
0: 'name',
1: 'age',
2: 'sex',
length: 3
}
即便如此留特,為什么叫做類數(shù)組對象呢伏恐?
那讓我們從讀寫孩哑、獲取長度、遍歷三個方面看看這兩個對象翠桦。
讀寫
console.log(array[0]); // name
console.log(arrayLike[0]); // name
array[0] = 'new name';
arrayLike[0] = 'new name';
長度
console.log(array.length); // 3
console.log(arrayLike.length); // 3
遍歷
for(var i = 0, len = array.length; i < len; i++) {
……
}
for(var i = 0, len = arrayLike.length; i < len; i++) {
……
}
是不是很像横蜒?
那類數(shù)組對象可以使用數(shù)組的方法嗎?比如:
arrayLike.push('4');
然而上述代碼會報錯: arrayLike.push is not a function
所以終歸還是類數(shù)組吶……
調(diào)用數(shù)組方法
如果類數(shù)組就是任性的想用數(shù)組的方法怎么辦呢销凑?
既然無法直接調(diào)用丛晌,我們可以用 Function.call 間接調(diào)用:
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
Array.prototype.join.call(arrayLike, '&'); // name&age&sex
Array.prototype.slice.call(arrayLike, 0); // ["name", "age", "sex"]
// slice可以做到類數(shù)組轉(zhuǎn)數(shù)組
Array.prototype.map.call(arrayLike, function(item){
return item.toUpperCase();
});
// ["NAME", "AGE", "SEX"]
類數(shù)組轉(zhuǎn)數(shù)組
在上面的例子中已經(jīng)提到了一種類數(shù)組轉(zhuǎn)數(shù)組的方法,再補(bǔ)充三個:
var arrayLike = {0: 'name', 1: 'age', 2: 'sex', length: 3 }
// 1. slice
Array.prototype.slice.call(arrayLike); // ["name", "age", "sex"]
// 2. splice
Array.prototype.splice.call(arrayLike, 0); // ["name", "age", "sex"]
// 3. ES6 Array.from
Array.from(arrayLike); // ["name", "age", "sex"]
// 4. apply
Array.prototype.concat.apply([], arrayLike)
那么為什么會講到類數(shù)組對象呢斗幼?以及類數(shù)組有什么應(yīng)用嗎澎蛛?
要說到類數(shù)組對象,Arguments 對象就是一個類數(shù)組對象孟岛。在客戶端 JavaScript 中瓶竭,一些 DOM 方法(document.getElementsByTagName()等)也返回類數(shù)組對象。
Arguments對象
接下來重點講講 Arguments 對象渠羞。
Arguments 對象只定義在函數(shù)體中斤贰,包括了函數(shù)的參數(shù)和其他屬性。在函數(shù)體中次询,arguments 指代該函數(shù)的 Arguments 對象荧恍。
function foo(name, age, sex) {
console.log(arguments);
}
foo('name', 'age', 'sex')
打印結(jié)果如下:
我們可以看到除了類數(shù)組的索引屬性和length屬性之外,還有一個callee屬性,接下來我們一個一個介紹送巡。
length屬性
Arguments對象的length屬性摹菠,表示實參的長度,舉個例子:
function foo(b, c, d){
console.log("實參的長度為:" + arguments.length)
}
console.log("形參的長度為:" + foo.length)
foo(1)
// 形參的長度為:3
// 實參的長度為:1
callee屬性
Arguments 對象的 callee 屬性骗爆,通過它可以調(diào)用函數(shù)自身次氨。
講個閉包經(jīng)典面試題使用 callee 的解決方法:
var data = [];
for (var i = 0; i < 3; i++) {
data[i] = function () {
console.log(arguments.callee.i);
};
data[i].i = i;
// (data[i] = function () {
// console.log(arguments.callee.i)
// }).i = i;
}
data[0]();
data[1]();
data[2]();
// 0
// 1
// 2
arguments 和對應(yīng)參數(shù)的綁定
function foo(name, age, sex, hobbit) {
console.log(name, arguments[0]); // name name
// 改變形參
name = 'new name';
console.log(name, arguments[0]); // new name new name
// 改變arguments
arguments[1] = 'new age';
console.log(age, arguments[1]); // new age new age
// 測試未傳入的是否會綁定
console.log(sex); // undefined
sex = 'new sex';
console.log(sex, arguments[2]); // new sex undefined
arguments[3] = 'new hobbit';
console.log(hobbit, arguments[3]); // undefined new hobbit
}
foo('name', 'age')
- 當(dāng)有實參傳入時,形參摘投,實參和 arguments 的值會共享(但并不是相同的命名空間煮寡。它們的命名空間是獨立的,但值是同步的)
- 當(dāng)沒有實參傳入時犀呼,形參與 arguments 值不會共享
- 在嚴(yán)格模式下幸撕,arguments對象的值和形參的值是獨立的,如下:
function test(num1,num2){
'use strict';
console.log(num1,arguments[0]);//1 1
arguments[0] = 2;
console.log(num1,arguments[0]);//1 2
num1 = 10;
console.log(num1,arguments[0]);//10 2
}
test(1);
傳遞參數(shù)
將參數(shù)從一個函數(shù)傳遞到另一個函數(shù)
// 使用 apply 將 foo 的參數(shù)傳遞給 bar
function foo() {
bar.apply(this, arguments);
}
function bar(a, b, c) {
console.log(a, b, c);
}
foo(1, 2, 3)