-
構造函數
是一種特殊的方法。主要用來在創建對象時初始化對象, 即為對象成員變量賦初始值,總與new運算符一起使用在創建對象的語句中。特別的一個類可以有多個構造函數 ,可根據其參數個數的不同或參數類型的不同來區分它們 即構造函數的重載。
人話:用來把一個對象構建起來的函數(給這個對象設定屬性啊參數啊定義之類的),就叫構造函數。function Foo (name, age) { //構造函數首字母大寫 this.name = name; this.age = age; this.class = 'class-1'; return this; } var f1 = new Foo (' zhangsan ', 20); var f2 = new Foo (' zhangsan ', 20); //Foo就是f1和f2的構造函數。
幫助理解
var a = {} 其實是var a = new Object() 的語法糖。
var a = [] 其實是var a = nwe Array() 的語法糖。
function Foo () {} 相當于 var Foo = new Function()
-
使用 instanceof 判斷一個函數是否是一個變量的構造函數
后面出現的Js內置函數,就是等號前面變量的構造函數
-
原型規則
- 所有引用類型(對象、數組、函數),都有對象特性,即都可以自由擴展屬性。
var obj = {}; obj.a = 100; var arr = []; arr.a = 100; function fn () {}; fn.a = 100; //都可以去給他們添加屬性。
- 所有的引用類型(對象、數組、函數),都有一個 " __proto__ " 屬性(約定稱之為隱式原型),屬性只是一個普通的對象。
console.log (obj.__proto__); console.log (arr.__proto__); console.log (fn.__proto__); //符合第一條規則,可以自由拓展屬性。
- 所有的函數,都有一個 “ prototype ” 屬性(約定稱之為顯示原型),屬性值也是一個普通對象。
console.log (fn.prototype); //函數也是引用類型,所以同時也符合第一條。
- 所有的引用類型(對象、數組、函數), " __proto__ " 屬性值指向它的構造函數的 “ prototype ” 屬性值
console.log (obj.__proto__ === Object.prototype); //true //obj是一個對象,而Object就是obj的構造函數。符合這一條
-
當試圖得到一個對象(函數、數組)的某個屬性時,如果對象本身沒有該屬性,就會去該對象的 __proto__(即該對象的構造函數的prototype)中尋找。
//創建一個構造函數Foo function Foo (name, age) { this.name = name; }; //給Foo的顯示原型添加一個屬性(函數) Foo.prototype.alertName = function () { alert (this.name); }; //創建對象 var f = new Foo ('zhangsan'); //Foo 就是 f 的構造函數 f.printName = function () { console.log (this.name); }; //測試 f.printName (); //f 本身有這個屬性,所以沒問題。 f.alertName (); //f 本身沒有這個屬性,所以就去f.__proto__里尋找, //即到它的構造函數Foo的prototype里尋找,并且可以找到。 //里面的this永遠只想自身f
- 補充——循環對象自身的屬性
當我們循環獲取對象自身屬性的時候,并不希望獲取到其隱式原型(其構造函數的顯示原型)的屬性。var item; for (intem in f) { if (f.hasOwnProperty(item)) { cosole.log (item); //雖然瀏覽器會在for in中屏蔽原型屬性,但加上會保證健壯性。 } }
- 所有引用類型(對象、數組、函數),都有對象特性,即都可以自由擴展屬性。
-
原型鏈
在上面,我們可以了解到,f.printName () 和 f.alertName () 是可以被找到的。
但如果再加上 f.toString () 呢,f 及其 Foo.prototype 中都沒有這個屬性。上面所說 f.__proto__ 即 Foo.prototype 的屬性值就是一個普通對象,也就是說有構造函數即Object。參照上面的原型規則可得出以后流程圖。
①
f.\_\_proto__ (Foo.prototype)
中找,找不到。
②f.__proto__.__proto__ (Foo.prototype.__proto__)(Object.prototype)
里找
就找到了。
但是,如果還是找不到呢
③ 繼續,到Object.prototype.__proto__
(有完沒完?)
④ 到了這里,為了避免死循環,Js規定,這里返回null。
圖片參考自慕課網
-
instanceof 判斷函數是否是構造函數
f instanceof Foo
——判斷Foo是否為 f 的構造函數。
答案是肯定的,邏輯是 f 的__proto__ 一層層往上看能否對應到 Foo.prototype在嘗試
f instanceof Object
——判斷Object
答案也是肯定的。網上找也可以找到 Object.prototype
Wait me back