《JavaScript設計模式》需要讀者具有一定的js基礎,否則不太容易看得懂,本人學習過程中就有諸多疑問點,也算崎嶇坎坷。建議大家可以先行閱讀《JavaScript高級程序設計》。
一、 定義函數的兩種方式
第一章的1.1 和 1.2小節其實是籠統的提出定義函數的兩種方式,下面是實例講解:
- 函數聲明
// 函數調用
say();
// 打印say
console.log(say);
// 函數聲明
function say() {
console.log("Hi");
}
test-1
test-1.png
- 函數表達式
// 打印say
console.log(say);
// 函數表達式
var say = function () {
console.log("Hi");
}
test-2
test-2.png
函數提升
- 對于函數聲明,js解釋器不僅提升了函數名,并且提升了函數的定義。即在程序最開始先解析函數定義,再執行其他代碼,所以可以在函數聲明之前調用。
test-1編譯后的代碼示意:
// 函數聲明
function say() {
console.log("Hi");
}
// 函數調用
say();
// 打印say
console.log(say);
- 對于函數表達式,js解釋器僅僅提升了變量名,當執行到函數體時才會開始解析。
test-2編譯過后代碼示意:
var say = undefined;
// 打印say
console.log(say);
// 函數表達式
say = function () {
console.log("Hi");
}
二、 對象
1.3 - 1.5小節都是關于如何多樣化創建對象,1.6 - 1.7小節是模擬類,1.8小節是鏈式調用。
為了減少覆蓋或被覆蓋的風險,可以使用對象封裝變量和函數。
- 對象字面量
var Person = {
say: function () {
console.log("Hi");
},
eat: function () {
console.log("eat");
}
}
- 點語法添加方法
這里通過點語法添加的是靜態方法,對象實例是無法訪問的!!!
var Person = function () {};
Person.say = function () {
console.log("Hi");
}
Person.eat = function () {
console.log("eat");
}
此時使用console.log()
打印Person結果為? () {}
,因為console.log(Person)
實際打印的是Person.toString()。
Function對象覆蓋了從object繼承來的Object.prototype.tostring方法,函數的tosting方法會返回一個表示函數源代碼的字符串。具體來說,包括 function關鍵字,形參列表,大括號,以及函數體中的內容。
建議使用console.dir()
打印。
匿名函數.png
- 簡易工廠
var Person = function () {
return {
say: function () {
console.log("Hi");
},
eat: function () {
console.log("eat");
}
}
}
- 類
var Person = function () {
// 公有方法
this.say = function () {
console.log("Hi");
},
this.eat = function () {
console.log("eat");
}
}
創建對象實例
var person = new Person();
- 原型
var Person = function () {};
// 原型方法
Person.prototype = {
say: function () {
console.log("Hi");
},
eat: function () {
console.log("eat");
}
}
- 鏈式調用
關鍵在于返回this
var Person = function () {};
Person.prototype = {
say: function () {
console.log("Hi");
return this;
},
eat: function () {
console.log("eat");
return this;
}
}
鏈式調用
var person = new Person();
person.say().eat()
三、 Function
- 函數式調用
注意下面this[name] = fn
,這句代碼相當于添加靜態方法,所以即使通過new關鍵字來創建新對象,對象實例也無法訪問類的靜態方法。
Function.prototype.addMethod = function(name, fn) {
// 這里相當于添加靜態方法
this[name] = fn;
return this;
}
// var methods = new Function (); 不建議使用
var methods = function () {};
// 鏈式添加
methods.addMethod('say', function () {
console.log("Hi");
return this;
}).addMethod('eat', function () {
console.log("eat");
return this;
});
// 鏈式調用
methods.say().eat();
- 類式調用
Function.prototype.addMethod = function(name, fn) {
// 這里相當于添加原型方法
this.prototype[name] = fn;
return this;
}
var Methods = new Function ();
Methods.addMethod('say', function () {
console.log("Hi");
return this;
}).addMethod('eat', function () {
console.log("eat");
return this;
});
var m = new Methods ();
m.say().eat();
參考
segmentfault conlog()是如何打印函數的
Function.prototype.string()
js中object轉化成string的過程