-
構(gòu)造函數(shù)
是一種特殊的方法贪庙。主要用來在創(chuàng)建對象時初始化對象蜘犁, 即為對象成員變量賦初始值,總與new運算符一起使用在創(chuàng)建對象的語句中止邮。特別的一個類可以有多個構(gòu)造函數(shù) 这橙,可根據(jù)其參數(shù)個數(shù)的不同或參數(shù)類型的不同來區(qū)分它們 即構(gòu)造函數(shù)的重載奏窑。
人話:用來把一個對象構(gòu)建起來的函數(shù)(給這個對象設(shè)定屬性啊參數(shù)啊定義之類的),就叫構(gòu)造函數(shù)屈扎。function Foo (name, age) { //構(gòu)造函數(shù)首字母大寫 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的構(gòu)造函數(shù)埃唯。
幫助理解
var a = {} 其實是var a = new Object() 的語法糖。
var a = [] 其實是var a = nwe Array() 的語法糖鹰晨。
function Foo () {} 相當(dāng)于 var Foo = new Function()
-
使用 instanceof 判斷一個函數(shù)是否是一個變量的構(gòu)造函數(shù)
后面出現(xiàn)的Js內(nèi)置函數(shù)墨叛,就是等號前面變量的構(gòu)造函數(shù)
-
原型規(guī)則
- 所有引用類型(對象、數(shù)組模蜡、函數(shù))漠趁,都有對象特性,即都可以自由擴展屬性哩牍。
var obj = {}; obj.a = 100; var arr = []; arr.a = 100; function fn () {}; fn.a = 100; //都可以去給他們添加屬性棚潦。
- 所有的引用類型(對象、數(shù)組膝昆、函數(shù)),都有一個 " __proto__ " 屬性(約定稱之為隱式原型)叠必,屬性只是一個普通的對象荚孵。
console.log (obj.__proto__); console.log (arr.__proto__); console.log (fn.__proto__); //符合第一條規(guī)則,可以自由拓展屬性纬朝。
- 所有的函數(shù)收叶,都有一個 “ prototype ” 屬性(約定稱之為顯示原型),屬性值也是一個普通對象共苛。
console.log (fn.prototype); //函數(shù)也是引用類型判没,所以同時也符合第一條。
- 所有的引用類型(對象隅茎、數(shù)組澄峰、函數(shù)), " __proto__ " 屬性值指向它的構(gòu)造函數(shù)的 “ prototype ” 屬性值
console.log (obj.__proto__ === Object.prototype); //true //obj是一個對象辟犀,而Object就是obj的構(gòu)造函數(shù)俏竞。符合這一條
-
當(dāng)試圖得到一個對象(函數(shù)、數(shù)組)的某個屬性時堂竟,如果對象本身沒有該屬性魂毁,就會去該對象的 __proto__(即該對象的構(gòu)造函數(shù)的prototype)中尋找。
//創(chuàng)建一個構(gòu)造函數(shù)Foo function Foo (name, age) { this.name = name; }; //給Foo的顯示原型添加一個屬性(函數(shù)) Foo.prototype.alertName = function () { alert (this.name); }; //創(chuàng)建對象 var f = new Foo ('zhangsan'); //Foo 就是 f 的構(gòu)造函數(shù) f.printName = function () { console.log (this.name); }; //測試 f.printName (); //f 本身有這個屬性出嘹,所以沒問題席楚。 f.alertName (); //f 本身沒有這個屬性,所以就去f.__proto__里尋找税稼, //即到它的構(gòu)造函數(shù)Foo的prototype里尋找烦秩,并且可以找到垮斯。 //里面的this永遠只想自身f
- 補充——循環(huán)對象自身的屬性
當(dāng)我們循環(huán)獲取對象自身屬性的時候,并不希望獲取到其隱式原型(其構(gòu)造函數(shù)的顯示原型)的屬性闻镶。var item; for (intem in f) { if (f.hasOwnProperty(item)) { cosole.log (item); //雖然瀏覽器會在for in中屏蔽原型屬性甚脉,但加上會保證健壯性。 } }
- 所有引用類型(對象、數(shù)組模蜡、函數(shù))漠趁,都有對象特性,即都可以自由擴展屬性哩牍。
-
原型鏈
在上面铆农,我們可以了解到牺氨,f.printName () 和 f.alertName () 是可以被找到的。
但如果再加上 f.toString () 呢墩剖,f 及其 Foo.prototype 中都沒有這個屬性猴凹。上面所說 f.__proto__ 即 Foo.prototype 的屬性值就是一個普通對象,也就是說有構(gòu)造函數(shù)即Object岭皂。參照上面的原型規(guī)則可得出以后流程圖郊霎。
①
f.\_\_proto__ (Foo.prototype)
中找,找不到爷绘。
②f.__proto__.__proto__ (Foo.prototype.__proto__)(Object.prototype)
里找
就找到了书劝。
但是,如果還是找不到呢
③ 繼續(xù)土至,到Object.prototype.__proto__
(有完沒完购对?)
④ 到了這里,為了避免死循環(huán)陶因,Js規(guī)定骡苞,這里返回null。
圖片參考自慕課網(wǎng)
-
instanceof 判斷函數(shù)是否是構(gòu)造函數(shù)
f instanceof Foo
——判斷Foo是否為 f 的構(gòu)造函數(shù)楷扬。
答案是肯定的解幽,邏輯是 f 的__proto__ 一層層往上看能否對應(yīng)到 Foo.prototype在嘗試
f instanceof Object
——判斷Object
答案也是肯定的。網(wǎng)上找也可以找到 Object.prototype
Wait me back