第八節(jié) 構(gòu)造函數(shù)

一、構(gòu)造函數(shù)模式


// 工廠函數(shù)模式

functionPerson(name,age){

varobj={};

obj.name=name;

obj.age=age;

obj.sayHello=function(){

console.log("My name is"+this.name,"I am "+this.age+" years old");

}

returnobj;

}

varp1=Person("chengxiaohui",18);

p1.sayHello();

================================

// 構(gòu)造函數(shù)模式

functionPerson(name,age){

this.name=name;

this.age=age;

this.sayHello=function(){

console.log("My name is"+this.name,"I am "+this.age+" years old");

}

}

// 多了一個(gè)new

varp1=newPerson("chengxiaohui",18);

p1.sayHello();

構(gòu)造函數(shù)模式和工廠函數(shù)模式的區(qū)別?

1、執(zhí)行的時(shí)候

普通函數(shù)執(zhí)行Person函數(shù)

構(gòu)造函數(shù)模式是通過new 執(zhí)行,那Person就是一個(gè)類了

函數(shù)執(zhí)行的返回值(p1)就是Person這個(gè)類的一個(gè)實(shí)例

2、在函數(shù)代碼執(zhí)行的時(shí)候

相同點(diǎn):

都是形成一個(gè)私有作用域,然后形參賦值->預(yù)解析(變量提升)->代碼從上向下執(zhí)行

不同點(diǎn):

在代碼執(zhí)行之前,不用自己手動(dòng)創(chuàng)建對(duì)象,瀏覽器會(huì)默認(rèn)創(chuàng)建一個(gè)對(duì)象數(shù)據(jù)類型的值(這個(gè)對(duì)象其實(shí)就是當(dāng)前類的一個(gè)實(shí)例)

this代表的就是當(dāng)前的實(shí)例,然后把屬性名和屬性值賦值給當(dāng)前的實(shí)例

最后瀏覽器會(huì)默認(rèn)把創(chuàng)建的這個(gè)對(duì)象返回

// 創(chuàng)建一個(gè)數(shù)組

var ary=[ ];//字面量方式創(chuàng)建

var ary2=new Array();//構(gòu)造函數(shù)創(chuàng)建

// 無論通過哪種方式去創(chuàng)建,ary和ary2都是Array這個(gè)類的實(shí)例

1、JS中所有的類都是函數(shù)數(shù)據(jù)類型,他通過new執(zhí)行變成一個(gè)類,但是本質(zhì)上他也是一個(gè)普通函數(shù)。

2、在構(gòu)造函數(shù)模式中,類中(函數(shù)體)出現(xiàn)的this.xxx=xxx中的this是當(dāng)前類的一個(gè)實(shí)例

3、p1和p2都是Person這個(gè)類的實(shí)例,所以都擁有sayHello這個(gè)方法,但是不同實(shí)例之間的方法是不一樣的,實(shí)例和實(shí)例之間是單獨(dú)的個(gè)體,所有的私有屬性不是同一個(gè)。

console.log(p1.sayHello===p2.sayHello);//false

構(gòu)造函數(shù)里面代碼執(zhí)行的時(shí)候的不同點(diǎn)

// 構(gòu)造函數(shù)模式

function Person(name, age) {

? //在構(gòu)造函數(shù)里,瀏覽器會(huì)默認(rèn)給你創(chuàng)建一個(gè)對(duì)象

? //var obj = {};

? obj.name = name;

? obj.age = age;

? obj.sayHello = function () {

? ? console.log("My name is" + this.name, "I am " + this.age + " years old");

? }

? //瀏覽器默認(rèn)返回了

? //return obj;

}

// 多了一個(gè)new

var p1 = new Person("chengxiaohui", 18);

var p2 = new Person("zhanghuan", 19);

p1.sayHello();

構(gòu)造函數(shù)執(zhí)行的時(shí)候不傳參數(shù)可以省略()

function Fn() {

}

//沒有寫調(diào)用的小括號(hào),但是依然會(huì)執(zhí)行這個(gè)函數(shù)

var f1 = new Fn;

//作為普通函數(shù)執(zhí)行必須要加小括號(hào)

Fn();

this的問題:在類中的出現(xiàn)的this.xxx=xxx中的this都是當(dāng)前類的實(shí)例,而某一個(gè)屬性值(方法),方法中的this需要看方法執(zhí)行的時(shí)候,前面是否有點(diǎn),才能知道this指向誰

function Fn(name, age) {

? // 這個(gè)this指的是f1

? this.name = name;

? this.age = age;

? this.sayHello = function () {

? ? //這里的this要看這個(gè)函數(shù)執(zhí)行的時(shí)候才知道

? ? console.log(this)

? }

}

var f1 = new Fn("chengxiaohui", 18);

f1.sayHello();//this 指的是f1

var f2=f1.sayHello;

f2();//this指的是window

類有普通函數(shù)的一面,當(dāng)函數(shù)執(zhí)行的時(shí)候,var num其實(shí)只是當(dāng)前形成的私有作用域中的私有變量而已,他和我們的f1這個(gè)實(shí)例沒有任何的關(guān)系

function Fn(name, age) {

? //創(chuàng)建的變量

? var num;

? this.name = name;

? this.age = age;

? this.sayHello = function () {

? ? console.log(this)

? }

}

var f1 = new Fn("chengxiaohui", 18);

f1.sayHello();

var f2=f1.sayHello;

f2();

構(gòu)造函數(shù)返回值的情況

默認(rèn)類中給返回了一個(gè)對(duì)象

如果寫了return,return的是基本數(shù)據(jù)類型的話,還是返回那個(gè)默認(rèn)對(duì)象

如果寫了return,return的是引用數(shù)據(jù)類型,返回的就是return的那個(gè)東西

instanceof

檢測某一個(gè)實(shí)例是都屬于這個(gè)類(引伸用途:檢測數(shù)據(jù)類型)語法:實(shí)例 instanceof 類

console.log(f1instanceofFn);

console.log(f1instanceofObject)

f1和f2都是Fn這個(gè)類的一個(gè)實(shí)例,都擁有name和sayHello兩個(gè)屬性,但是這兩個(gè)屬性是各自的私有屬性

functionFn(name){

this.name=name;

this.sayHello=function(){

console.log(this)

}

}

varf1=newFn("chengxiaohui");

varf2=newFn("zhanghuan");

二、原型

構(gòu)造函數(shù)模式中擁有了類和實(shí)例的概念,并且實(shí)例和實(shí)例之間是相互獨(dú)立的-->實(shí)例識(shí)別如何將一個(gè)私有屬性提升為公有屬性呢?

functionFn(name){

this.name=name;

}

//放在原型上成了公有屬性

Fn.prototype.sayHello=function(){

console.log("I can say hello~");

}

varf1=newFn("chengxiaohui");

varf2=newFn("zhanghuan");

需要焊死在腦子里的三句話

1、每一個(gè)函數(shù)數(shù)據(jù)類型都有一個(gè)天生自帶的屬性:prototype(原型),這個(gè)屬性值是一個(gè)對(duì)象數(shù)據(jù)類型

2、在prototype上瀏覽器天生給他加了一個(gè)constructor屬性,屬性值是當(dāng)前函數(shù)(類)本身

3、每一個(gè)對(duì)象也天生自帶一個(gè)屬性:__proto__,屬性值是當(dāng)前實(shí)例所屬類的原型

所有的函數(shù):普通函數(shù)、類(內(nèi)置類,自定義類)都是Function的實(shí)例,F(xiàn)unction 和Object 都是Function的實(shí)例

所有的函數(shù)身上都有一個(gè)prototype 和__proto__


畫圖解析

Object是JS中所有對(duì)象數(shù)據(jù)類型的基類(最頂層的類)

f1 instanceof Object->true因?yàn)閒1通過__proto__可以向上查找,不管有多少級(jí),最終都會(huì)找到Object上

三、原型鏈查找機(jī)制

f1.hasOwnProperty("x")

1、通過對(duì)象.屬性名的方式獲取到屬性值的時(shí)候,首先在對(duì)象的私有屬性上進(jìn)行查找,如果私有屬性上有,就是私有的這個(gè)

2、如果私有屬性沒有,則通過__proto__找到所屬類的原型(類的原型上定義的屬性和方法都是當(dāng)前實(shí)例的公有屬性和方法)

3、如果原型上也沒有,則繼續(xù)通過原型的__proto__繼續(xù)向上查找,一直到Object.prototype為止

這種查找機(jī)制我們就叫做原型鏈模式!

四、習(xí)題

function Fn(){

? ? this.x=100;

? ? this.y=200;

? ? this.getX=function(){

? ? ? ? console.log(this.x);

? ? }

}

Fn.prototype.getX=function(){

? ? console.log(this.x);

}

Fn.prototype.getY=function(){

? ? console.log(this.y);

}

var f1=new Fn;

var f2=new Fn;

console.log(f1.getX==f2.getX);

console.log(f1.getY==f2.getY);

console.log(f1.__proto__.getY==Fn.prototype.getY);

console.log(f1.__proto__.getX==f2.getX);

console.log(f1.getX===Fn.prototype.getX);

console.log(f1.constructor);

console.log(Fn.prototype.__proto__.constructor);

f1.getX();

f1.__proto__.getX();

f2.getY();

Fn.prototype.getY();

============================

function fun(){

? ? this.a=0;

? ? this.b=function(){

? ? ? ? alert(this.a);

? ? }

}

fun.prototype={

? ? b:function(){

? ? ? ? this.a=20;

? ? ? ? alert(this.a);

? ? },

? ? c:function(){

? ? ? ? this.a=30;

? ? ? ? alert(this.a)

? ? }

};

var my_fun=new fun();

my_fun.b();

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容