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
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。