這幾天發現了一本好書,又薄又精闢,《JavaScript語言精粹》
看了對象、函數這兩節,發現書如其名,確實是精粹。
函數的調用
函數調用的方式有四種:
- 方法調用模式
- 函數調用模式
- 構造器調用模式
- apply調用模式
方法調用模式
這個方法是經常會見到的一種模式,方法作爲對象的一種屬性,通過obj.functionName()這種調用方式調用,如:
var myObject = {
value: 0;
increment: function(inc) {
this.value += typeof inc === 'number' ? inc : 1; //默認增加爲1
}
}
myObject.increment(); //方法調用模式
console.log(myObject.value); //1
myObject.increment(2);
console.log(myObject.value); //3
方法調用的好處就是,this綁定的是調用該方法的對象,因此它可以訪問myObj.value
函數調用模式
當一個函數並非一個對象的屬性時,那麼它被當作一個函數來調用:
var sum=add(3,4)
當採用這種方式調用時,this被綁定到全局對象。
例如:
var a = 'gloabal:';
function test() {
var a = 'add:';
return (function() {
return this.a + 1;
})()
}
var sum = test();
console.log(sum);//global:1
按道理來講,test裏面的匿名函數應該訪問test的a,但是this卻指向了global;
如果聲明“use strict” ,會報異常:Cannot read property ‘a’ of undefined
作者說這是JavaScript語言設計上的錯誤。倘若語言設計正確,當內部函數被調用時,this應該仍然綁定到外部函數的this變量。
解決方法:
function add(a, b) {
return a + b;
}
var myObject = {
value: 1,
getValue: function() {
return this.value;
}
}
myObject.double = function() {
var that = this;
var helper = function() {
that.value = add(that.value, that.value);
}
helper(); //以函數方式調用helpher
}
myObject.double();
console.log(myObject.getValue()); //2
構造器調用模式
javascript是一門基於原型繼承的語言。這意味着對象可以直接從其他對象繼承屬性。
書中的例子:
var Quo = function(string) {
this.status = string;
}
Quo.prototype.get_status = function(first_argument) {
return this.status;
};
var myQuo = new Quo('Confused');
console.log(myQuo.get_status());
說明:
1、這裏聲明瞭一個Quo類
2、Quo具有屬性status,和原型方法get_status
3、因爲get_status是Quo的原型屬性,因此this指向調用Quo的對象
這種結合new前綴調用的函數,就被稱作是構造器函數了。
如果調用函數沒有在前面加上new,會發生非常糟糕的事情,既沒有編譯時的警告,也沒有運行時警告,所以大寫約定非常重要。
apply調用模式
javascrip是一門函數式的面向對象編程語言,所以函數可以擁有方法。
apply方法讓我們可以構建一個參數並用其去調用函數,它也允許我們選擇this的值,apply方法接收兩個參數。第一個是將被綁定給this的值,第二個是一個參數數組
var array = [3, 4];
var sum = add.apply(null, array);
/*延續demo3,利用apply,不需要new關鍵字,把對象statusObject通過apply傳遞*/
var statusObject = {
status: 'A-OK'
};
var Quo = function(string) {
this.status = string;
}
Quo.prototype.get_status = function(first_argument) {
return this.status;
};
var status = Quo.prototype.get_status.apply(statusObject);
console.log(status);