js難點(diǎn)之原型,真難?
構(gòu)造函數(shù)的首字母必須大寫(xiě),用來(lái)區(qū)分于普通函數(shù);
這里的this指向?qū)嵗蟮膶?duì)象p;
function P(name) {
this.name=name;
this.say=function(){
console.log("我是"+this.name)//我是毛敏;
}
}
P.prototype.money="一百萬(wàn)";
P.prototype.name="maomin";
var p=new P("毛敏");//實(shí)例化
alert(p.name);
p.say();//使用這個(gè)方法
console.log(p.name+"有"+p.money)
所以有兩種方法:
1.通過(guò)構(gòu)造函數(shù)在函數(shù)內(nèi)直接this打點(diǎn),相當(dāng)于創(chuàng)建一個(gè)屬性。
2.通過(guò)給構(gòu)造函數(shù)一個(gè)prototype。(只有構(gòu)造函數(shù)才有prototype屬性)
注意實(shí)例化后的對(duì)象沒(méi)有prototype,如:p.prototype.a=“123”;console.log(p.a);這樣是錯(cuò)誤的。只有函數(shù)對(duì)象才有prototype.那么什么是函數(shù)對(duì)象,凡是通過(guò)new Function創(chuàng)建的對(duì)象就叫做函數(shù)對(duì)象。函數(shù)對(duì)象可以創(chuàng)建普通對(duì)象,但是普通對(duì)象不能創(chuàng)建函數(shù)對(duì)象。通常普通對(duì)象是通過(guò)Object創(chuàng)建的。
javascript中,每個(gè)對(duì)象都會(huì)在內(nèi)部生成一個(gè)proto 屬性,當(dāng)我們?cè)L問(wèn)一個(gè)對(duì)象屬性時(shí),如果這個(gè)對(duì)象不存在就回去proto 指向的對(duì)象里面找,一層一層找下去,這就是javascript原型鏈的概念。
p.proto ==> P.prototype ==> P.prototype.proto ==> Object.prototype ==> Object.prototype.proto ==>null
JS中所有的東西都是對(duì)象,所有的東西都由Object衍生而來(lái), 即所有東西原型鏈的終點(diǎn)指向null
1、每一個(gè)函數(shù)對(duì)象都有一個(gè)prototype屬性,但是普通對(duì)象是沒(méi)有的;
prototype下面又有個(gè)construetor,指向這個(gè)函數(shù)。
2、每個(gè)對(duì)象都有一個(gè)名為_(kāi)proto_的內(nèi)部屬性,指向它所對(duì)應(yīng)的構(gòu)造函數(shù)的原型對(duì)象,原型鏈基于_proto_;
好了,開(kāi)始上代碼和例子,建一個(gè)普通對(duì)象,我們可以看到
1、p的確沒(méi)有prototype屬性
2、p是P的實(shí)例
3、p的__proto__指向P的prototype
4、Object.prototype.constructor指向Object本身
P.prototype.job=function(){
console.log("我是一名前端工程師");
}
var data={
"age":"21",
"gender":"boy"
}
p.job();//我是一名前端開(kāi)發(fā)工程師;
console.log(data.age)
alert(p.name)//會(huì)彈出毛敏,而不會(huì)彈出maomin,函數(shù)對(duì)象本身的屬性或方法的優(yōu)先級(jí)要高于原型的屬性或方法。
console.log(P.__proto__.constructor);//Function()
console.log(P.prototype.__proto__.constructor);//Object()
這里我們來(lái)總結(jié)一下prototype與_proto_之間的關(guān)系
new F().proto === F.prototype // true
前者是實(shí)例化的對(duì)象,后者是函數(shù)對(duì)象。
因?yàn)镺bject是一個(gè)函數(shù),函數(shù)的構(gòu)造器都是Function
Object.proto === Function.prototype // true
通過(guò)函數(shù)字面量定義的函數(shù)的__proto__屬性都指向Function.prototype
(function(){}).proto === Function.prototype // true
通過(guò)對(duì)象字面量定義的對(duì)象的__proto__屬性都是指向Object.prototype
({}).proto === Object.prototype // true
Object函數(shù)的原型的__proto__屬性指向null
Object.prototype.proto === null // true
因?yàn)镕unction本身也是一個(gè)函數(shù),所以Function函數(shù)的__proto__屬性指向它自身的prototype
Function.proto === Function.prototype // true
因?yàn)镕unction的prototype是一個(gè)對(duì)象,所以Function.prototype的__proto__屬性指向Object.prototype
Function.prototype.proto === Object.prototype // true
下面的代碼是又重新闡述了_proto_的屬性。
var a={};
a.__proto__.name="maomin";
console.log(a.__proto__.constructor);//Object()
console.log(a.name)
var b=function(){};
console.log(b.__proto__.constructor);//Function()
var c=String();
console.log(c.__proto__.constructor);//String()
//通過(guò)上面幾個(gè)數(shù)據(jù)類(lèi)型的演示,知道了__proto__是每個(gè)對(duì)象都有的屬性。
function A(name) {
this.name=name
}
var a=new A("maomin")
console.log(a.constructor)
作者:Vam的金豆之路
主要領(lǐng)域:前端開(kāi)發(fā)
我的微信:maomin9761
微信公眾號(hào):前端歷劫之路