深刻學習js之——類數組對象與arguments #11

深刻學習js系列是本身階段性成長的見證,但願經過文章的形式更加嚴謹、客觀地梳理js的相關知識,也但願可以幫助更多的前端開發的朋友解決問題,期待咱們的共同進步。前端

若是以爲本系列不錯,歡迎點贊、評論、轉發,您的支持就是我堅持的最大動力。數組


類數組對象

所謂的類數組對象:微信

擁有一個 length 屬性和若干索引屬性的對象閉包

舉個例子:app

var array = ['name','age','sex'];

  var arrayLike ={
    0: 'name',
    1'age',
    2: 'sex',
    length: 3
  }
複製代碼

即使如此,爲何叫作類數組對象呢?函數

那讓咱們從讀寫、獲取長度、遍歷這三個方面看看這兩個對象:post

讀寫

console.log(array.length); // 3
console.log(arrayLike.ength); // 3
複製代碼

遍歷

for(var i = 0,len = array.length;i<len;i++){
  ……
}

for(var i = 0,len = arrayLike.length;i<len;i++){
  ……
}
複製代碼

是否是很像 那類數組對象可使用數組的方法嗎?好比:學習

arrayLike.push("4");
複製代碼

然而 上述代碼會報錯: arrayLike.push is not a function測試

因此終歸仍是類數組,哈哈哈ui

調用數組的方法

若是類數組就是任性的想要使用數組的方法怎麼辦呢?

既然沒法直接的調用,咱們可使用 Function.call 間接調用:

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能夠作到類數組轉數組
  Array.prototype.map.call(arrayLike, function(item){
    return item.toUpperCase();
  });
  // ["NAME", "AGE", "SEX"]
複製代碼

類數組轉數組

在上面的例子中已經提到了一種類數組轉數組的方法,再補充三個:

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)
複製代碼

那麼爲何要講到類數組對象呢?以及類數組對象有什麼做用嗎?

要說到類數組對象,Arguments 對象就是一個類數組對象。在客戶端 JavaScript 這種,一些 DOM 方法

document.getElementsByTagName();
複製代碼

等也返回類數組對象。

Arguments 對象

接下來重點講講 Arguments 對象

Arguments 對象只定義在函數體中,包括了函數的參數和其餘屬性,在函數體中,arguments 指代該函數的 Arguments 對象

舉一個例子:

function foo(name, age, sex) {
  console.log(arguments);
}
foo("name", "age", "sex");
複製代碼

打印結果以下:

咱們能夠看到除了類數組的索引屬性和 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 屬性,經過它能夠調用函數自身。 講一個閉包經典米娜會題中使用 callee 的解決方法:

var data = [];

for (var i = 0; i < 3; i++) {
  (data[i] = function() {
    console.log(arguments.callee.i);
  }).i = i;
}

data[0]();
data[1]();
data[2]();

// 0
// 1
// 2
複製代碼

接下來說講 arguments 對象的幾個注意要點:

arguments 和對應參數的綁定

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");
複製代碼

傳入的參數,實參和 arguments 的值會共享,當沒有傳入時,實參與 arguments 值不會共享

除此以外,以上是在非嚴格模式下,若是是在嚴格模式下,實參和 arguments 是不會共享的。

傳遞參數

將參數從一個函數傳遞到另一個函數

// 使用apply 將foo 的參數傳遞給bar
function foo() {
  bar.apply(this, arguments);
}

function bar(a, b, c) {
  console.log(a, b, c);
}

foo(1, 2, 3);
複製代碼

強大的 ES6

使用 ES6 的 ... 運算符,咱們能夠輕鬆的轉成數組

function func(...arguments) {
  console.log(arguments); // [1,2,3]
}
func(1, 2, 3);
複製代碼

應用

arguments的應用其實不少,若是要總結這些場景的話,暫時能想到的包括:

參數不定長 函數柯里化 遞歸調用 函數重載 ...

深刻學習JavaScript系列目錄

歡迎添加個人我的微信討論技術和個體成長。

歡迎關注個人我的微信公衆號——指尖的宇宙,更多優質思考乾貨

相關文章
相關標籤/搜索