1. 程式人生 > >Javascript 中call() , applay()理解

Javascript 中call() , applay()理解

call, apply都屬於Function.prototype的一個方法,它是JavaScript引擎內在實現的,因為屬於Function.prototype,所以每個Function物件例項,也就是每個方法都有call, apply屬性.既然作為方法的屬性,那它們的使用就當然是針對方法的了.這兩個方法是容易混淆的,因為它們的作用一樣,只是使用方式不同.

相同點: 兩個方法產生的作用是完全一樣的, apply:方法能劫持另外一個物件的方法,繼承另外一個物件的屬性.

不同點: 方法傳遞的引數不同

Function.apply(obj,args)

 Function.apply(obj,args)方法能接收兩個引數
 obj:這個物件將代替Function
類裡this物件 args:這個是陣列,它將作為引數傳給Function(args-->arguments

Function.call(obj,[param1[,param2[,…[,paramN]]]])

 Function.call(obj,[param1[,param2[,…[,paramN]]]])
 obj:這個物件將代替Function類裡this物件
 params:這個是一個引數列表

使用場景:(引數數量是不是固定)

當你的引數是明確知道數量時,用 call;
而不確定的時候,用 apply,然後把引數 push 進陣列傳遞進去。當引數數量不確定時;
函式內部也可以通過 arguments 這個陣列來遍歷所有的引數。

foo.call(this, arg1,arg2,arg3) 
== foo.apply(this, arguments)
== this.foo(arg1, arg2, arg3)
function people(){}
people.prototype={     
    name:"Tom",    
    say: function(){alert("my name is "+this.name);}
}
var Tom = new people;
Tom.say();

如果我們有一個物件Li = {name:”Li”},我們不想對它重新定義say方法,那麼我們可以通過 call() 或 apply() 用 Tom

的say方法:

var Li = {name:"Li"}
Tom.say.call(Li);

call 和 apply 是為了動態改變this而出現的,當一個object沒有某個方法,但是其他的有,我們可以藉助call或apply用其它物件的方法來操作。

應用場景:
通過document.getElementsByTagName選擇的dom 節點是一種類似array的array。它不能應用Array下的push,pop等方法。
我們可以通過:

var domNodes = Array.prototype.slice.call(document.getElementsByTagName("*"),0);

這樣domNodes就可以應用Array下的所有方法了。

貓吃魚,狗吃肉,奧特曼打小怪獸。
有天狗想吃魚了
貓.吃魚.call(狗,魚)
狗就吃到魚了
貓成精了,想打怪獸
奧特曼.打小怪獸.call(貓,小怪獸)

ECMAScript6 引入了一套新的關鍵字用來實現 class。

JavaScript 仍然基於原型。這些新的關鍵字包括 class, constructor,static,extends 和 super。

class Polygon {
  constructor(height, width) {
    this.height = height;
    this.width = width;
  }
}

class Square extends Polygon {
  constructor(sideLength) {
    super(sideLength, sideLength);
  }
  get area() {
    return this.height * this.width;
  }
  set sideLength(newLength) {
    this.height = newLength;
    this.width = newLength;
  }
}

var square = new Square(2);

效能
在原型鏈上查詢屬性比較耗時,另外,試圖訪問不存在的屬性時會遍歷整個原型鏈。

要檢查物件是否具有自己定義的屬性,而不是其原型鏈上的某個屬性,則必須使用所有物件從Object.prototype繼承的 hasOwnProperty 方法。

擴充套件內建原型的唯一理由是支援JavaScript 引擎的新特性,如Array.forEach。