一、原型判斷方法
*術(shù)語(yǔ)解釋:成員=屬性+方法
實(shí)例成員:實(shí)例屬性和實(shí)例方法
原型成員:原型對(duì)象屬性和原型對(duì)象方法
1箕戳、原型對(duì)象:每個(gè)構(gòu)造函數(shù)都有一個(gè)與之相關(guān)聯(lián)的對(duì)象,這個(gè)對(duì)象稱之為原型對(duì)象躏率。 (相關(guān)聯(lián)是指通過(guò)一個(gè)prototype屬性來(lái)連接這個(gè)對(duì)象衩侥,然后原型對(duì)象可以通過(guò) constructor回到構(gòu)造函數(shù))
2、特點(diǎn):構(gòu)造函數(shù)的原型對(duì)象上的所有屬性和方法會(huì)被構(gòu)造函數(shù)創(chuàng)建出來(lái)的所有對(duì)象共享刨晴。
3屉来、 訪問(wèn)原型對(duì)象:(1) prototype
(2)proto
(3)object.getPrototypeof()
4、設(shè)置原型對(duì)象:(1)動(dòng)態(tài)特性(利用prototype屬性直接添加狈癞,)
(2)使用字面量替換(1茄靠、在替換前創(chuàng)建出的對(duì)象和替換后創(chuàng)建出的對(duì)象,他們所指向的原型對(duì)象不是同一個(gè)原型對(duì)象蝶桶。2慨绳、修改constructor指向)
(3)系統(tǒng)的原型對(duì)象只可以添加屬性和方法,不能替換或刪除真竖。
5脐雪、(1)hasownproperty: 檢查對(duì)象中是否存在制定的屬性(不包含原型成員)。
作用:過(guò)濾處理恢共,過(guò)濾原型對(duì)象成員战秋。
(2) in 檢查對(duì)象中是否存在制定的屬性(包含原型成員)。
(3)isPrototypeof()檢查某個(gè)對(duì)象是否是指定對(duì)象的原型對(duì)象讨韭。(包含原型鏈)
(4)object.getpototypeof():獲取某個(gè)對(duì)象的原型對(duì)象脂信。
(5)instanceof :判斷某個(gè)構(gòu)造函數(shù)的原型對(duì)象是否在當(dāng)前的原型鏈上面。
6透硝、call方法和apply方法:借用其他對(duì)象的方法狰闪,并且綁定方法的內(nèi)部this。方法是在函數(shù)Fuction原型對(duì)象上的濒生。所有的函數(shù)對(duì)象都可以調(diào)用埋泵。
<script>
var obj={
name:'jane',
show: function (a,b) {
console.log(this.name + ":" + a + b);
}
};
var obj1={name:'jack ' };
obj.show(1,2);
obj.show.call(obj1,2,2); //方法在調(diào)用時(shí)會(huì)立刻執(zhí)行。后面的參數(shù)借用前者方法甜攀。
//實(shí)參傳遞不是應(yīng)該寫(xiě)在調(diào)用函數(shù)的后面秋泄。
</script>
call和 aplly區(qū)別:傳參方式不同琐馆,call可以接受多個(gè)參數(shù),但apply方法只接受連兩個(gè)參數(shù)恒序,后面的實(shí)參需要寫(xiě)入到一個(gè)字符串中瘦麸;
形參的默認(rèn)長(zhǎng)度不一樣。(函數(shù)的length屬性歧胁,獲取的是函數(shù)形參的個(gè)數(shù))
7.this關(guān)鍵字:指向一個(gè)對(duì)象滋饲,具體到某一個(gè)由當(dāng)前上下文決定。在函數(shù)的內(nèi)部喊巍,和函數(shù)的調(diào)用方法有關(guān)屠缭。
7.1函數(shù)調(diào)用方式: A、直接調(diào)用(指向window)
function demo1(){ console.log(this); }
demo1();//
B崭参、對(duì)象的方法調(diào)用(指向調(diào)用該方法的object)
function demo1(){ console.log(this);}
var obj={}
obj.demo=demo1;
obj.demo();
C:構(gòu)造函數(shù)的方式調(diào)用(指向新創(chuàng)建的對(duì)象)
function demo1(){ console.log(this);}
var obj= new demo1();
console.log(obj);
D:函數(shù)上下文調(diào)用(傳遞的第一個(gè)參數(shù))
call和apply
7.2(重點(diǎn))this的對(duì)視問(wèn)題
var demo1={
name:'123',
show: function () {
console.log(this.name)}
};
var t=demo1.show;
t();
用函數(shù)t直接調(diào)用對(duì)象方法時(shí)呵曹,相當(dāng)于在賦值之后,已經(jīng)脫離了原對(duì)象何暮,此時(shí)t內(nèi)部的this變量已經(jīng)獨(dú)立出來(lái)奄喂,和源對(duì)象沒(méi)有了關(guān)系,此時(shí)的this已經(jīng)指向了Window海洼,運(yùn)行后跨新,在window中查詢自定義的方法,未查詢到的情況下輸出空字符坏逢。
8.tostring方法:轉(zhuǎn)換為字符串域帐,以字符串的方式來(lái)描述對(duì)象。 返回值是一個(gè)數(shù)組是整,有兩個(gè)參數(shù)肖揣,他們分別表示 [對(duì)象類型,構(gòu)造函數(shù)類型]
但數(shù)組類型的返回值是數(shù)組中的值浮入,原因在于數(shù)組的tostring方法在數(shù)組的原型對(duì)象中單獨(dú)存在许饿,所以需要借用對(duì)象類型原型的方法來(lái)做為判斷,
Object.prototype.toString.call()
- Array.isAarray判斷某個(gè)對(duì)象是否是數(shù)組類型舵盈。
注意點(diǎn):這個(gè)方法是ES5的,存在兼容性問(wèn)題球化。需要自定義一個(gè)函數(shù)來(lái)解決此問(wèn)題秽晚。
二、繼承
1筒愚、繼承分類:(1)赴蝇、基于接口的繼承(2)基于實(shí)現(xiàn)的繼承
2、javascript使用了一種獨(dú)特繼承機(jī)制——原型繼承(不包含原型成員 )巢掺。prototype屬性句伶,是建立這種機(jī)制的關(guān)鍵劲蜻,這個(gè)屬性存在于每一個(gè)構(gòu)造函數(shù)中。
3考余、實(shí)現(xiàn)方式:
(1)屬性拷貝
1.1 屬性拷貝分為:淺拷貝和深拷貝
存在問(wèn)題:A、如果要拷貝多個(gè)對(duì)象需要多次for……in循環(huán)。B焕蹄、如果屬性是引用類型塔粒,存在共享問(wèn)題;
解決問(wèn)題A:使用object.assign來(lái)解決多次拷貝問(wèn)題身冬。
作用:拷貝對(duì)個(gè)對(duì)象的屬性衅胀。
語(yǔ)法:object.assign(目標(biāo)對(duì)象,源對(duì)象1酥筝,源對(duì)象2 …………)
注意點(diǎn):---ES6退出的新方法滚躯,使用需要注意兼容性。
---存在同名屬性會(huì)被按照參數(shù)順序覆蓋嘿歌。
---有返回值掸掏,為目標(biāo)對(duì)象。
---如果只傳遞一個(gè)參數(shù)搅幅,直接返回當(dāng)前對(duì)象阅束。如果不是對(duì)象,會(huì)轉(zhuǎn)
換為對(duì)應(yīng)的包裝對(duì)象茄唐。
---如果是null或者undefined息裸,會(huì)報(bào)錯(cuò)。
---目標(biāo)對(duì)象正常沪编,其他值會(huì)忽略處理其他值呼盆。字符串會(huì)特殊處理為
數(shù)組對(duì)象來(lái)處理,
---同樣存在共享問(wèn)題蚁廓。
1.2 用深拷貝解決共享問(wèn)題:
淺拷貝在對(duì)對(duì)象進(jìn)行拷貝時(shí)访圃,傳遞的是地址,所以存在數(shù)據(jù)共享的問(wèn)題相嵌。
方案:遍歷對(duì)象的過(guò)程中腿时,值類型直接賦值,屬性為引用類型饭宾,添加一個(gè)引用類型的屬性批糟,添加的時(shí)被添加的對(duì)象中并不存在一個(gè)引用類型的值,所以需要在內(nèi)部初始化一個(gè)引用類型看铆。屬性的值為一個(gè)引用類型徽鼎,然后遍歷,再賦值。
具體代碼實(shí)現(xiàn):
function deepcopy(obj,obj1){
obj=obj||{};
for(var key in obj1){
if(typeof obj1[key]=='object'){
obj[key]={};
deepcopy(obj[key],obj1[key])
}else{
obj[key]=obj1[key]
}
}
}
存在缺點(diǎn):在循環(huán)遍歷初始化中否淤,無(wú)法對(duì)數(shù)組類型做出正確的判斷悄但,被解析成了object類型屬性,所以需要進(jìn)行改進(jìn)石抡。
在添加對(duì)象初始化中:用Array.isArray判斷:
obj[key]=Array.isArray(obj1[key])?[]:{};
(2)原型式繼承
第一種實(shí)現(xiàn)方式:
1.1 ---提供構(gòu)造函數(shù)
1.2---設(shè)置構(gòu)造函數(shù)原型的成員
1.3---直接在原型對(duì)象寫(xiě)入方法的缺點(diǎn):
(a) 團(tuán)隊(duì)開(kāi)發(fā)會(huì)出現(xiàn)相同屬性名覆蓋的問(wèn)題檐嚣,造成混亂,
(b)性能不好汁雷,和屬性的訪問(wèn)方式相關(guān)净嘀,原型對(duì)象的屬性增
多,遍歷的復(fù)雜度會(huì)上升侠讯。
1.4--- 如何克服缺點(diǎn):安全擴(kuò)展原型對(duì)象
提供自己的構(gòu)造函數(shù)挖藏;設(shè)置構(gòu)造函數(shù)的原型對(duì)象;在自己提
供的構(gòu)造函數(shù)原型對(duì)象上添加成員厢漩;然后用自己的構(gòu)造函數(shù)創(chuàng)建
對(duì)象膜眠。引出了第二種實(shí)現(xiàn)方式。
第二種實(shí)現(xiàn)方式:
1.1 ---提供構(gòu)造函數(shù)
1.2---設(shè)置構(gòu)造函數(shù)原型對(duì)象溜嗜,然后替換掉構(gòu)造函數(shù)原來(lái)的原
型宵膨。
對(duì)象,并且同時(shí)需要修正構(gòu)造器的constructior屬性炸宵,使它指向原
實(shí)例對(duì)象的構(gòu)造函數(shù)辟躏。
第三種實(shí)現(xiàn)方法:
1.1---提供父構(gòu)造函數(shù)
1.2---設(shè)置父構(gòu)造函數(shù)的原型對(duì)象
1.3---提供子構(gòu)造函數(shù)
1.4---設(shè)置子構(gòu)造函數(shù)的原型對(duì)象
1.5---創(chuàng)建對(duì)象(子函數(shù)原型對(duì)象替換為父函數(shù)原型對(duì)象)
缺點(diǎn):a:無(wú)法獲取父構(gòu)造函數(shù)的實(shí)例成員;b:存在共享問(wèn)題土全。
無(wú)法共享的可以通過(guò)原型鏈來(lái)解決(原型鏈繼承)捎琐,但依然存在
共享問(wèn)題。
(3)原型鏈繼承
** 原型鏈結(jié)構(gòu):
1.1 所有的對(duì)象都是由構(gòu)造函數(shù)創(chuàng)建出來(lái)裹匙,每個(gè)對(duì)象都有相對(duì)應(yīng)的
構(gòu)造函數(shù)瑞凑,
1.2每個(gè)構(gòu)造函數(shù)都有一個(gè)與之相關(guān)聯(lián)的原型對(duì)象。
1.3構(gòu)造函數(shù)原型對(duì)象本身也是對(duì)象概页,因此籽御,構(gòu)造函數(shù)原型對(duì)象也
有自己的構(gòu)造函數(shù)。
1.4構(gòu)造函數(shù)原型對(duì)象的構(gòu)造函數(shù)也有相關(guān)聯(lián)的原型對(duì)象惰匙。而這個(gè)
原型對(duì)象也是對(duì)象技掏。
以上是一種鏈?zhǔn)降脑L問(wèn)結(jié)構(gòu),JS對(duì)原型鏈的終點(diǎn)進(jìn)行了特殊處理项鬼,
object.prototype._prto_=null零截。
** 原型鏈搜索規(guī)則:對(duì)象在訪問(wèn)屬性時(shí),首先在自身查找秃臣,然后
去自己的原型對(duì)象,然后去原型對(duì)象的原型對(duì)象。一直重復(fù)到找到奥此。
屬性和方法在位沒(méi)有找到的情況下弧哎,會(huì)出現(xiàn)屬性未定義,方法報(bào)錯(cuò)的情
況稚虎。
1.5 注意點(diǎn):a:代碼的書(shū)寫(xiě)順序撤嫩,完成原型鏈繼承之后,再修改
constructor屬性指向構(gòu)造函數(shù)蠢终,然后添加原型成員序攘;b:無(wú)法向父函數(shù)傳遞
參數(shù)。父構(gòu)造函數(shù)的實(shí)例對(duì)象的實(shí)例成員會(huì)自動(dòng)成為子構(gòu)造函數(shù)的實(shí)例
成員的原型成員寻拂。
1.6 object.create()該方法用來(lái)創(chuàng)建一個(gè)對(duì)象程奠,并且設(shè)置創(chuàng)建的對(duì)象的
原型對(duì)象為他括號(hào)內(nèi)參數(shù)指定的某一對(duì)象。
注意點(diǎn):ES5推出的祭钉,有兼容性問(wèn)題瞄沙,(自定義一個(gè)新方法)
實(shí)現(xiàn)步驟為:先自定義一個(gè)空函數(shù)后,并設(shè)置其原型對(duì)象慌核,然后返回距境。
<script>
function Animal(){
this.color='紅色的老王';
};
Animal.eat= function () {
console.log('eat');
}
function Person(){
this.name='人中老王';
}
Person.prototype= new Animal();
Person.prototype.constructor=Person;
Person.prototype.say= function () {
console.log('hello');
}
function Student(){
this.number='123456789'
}
Student.prototype=new Person();
Student.prototype.constructor=Student;
Student.prototype.study= function () {
console.log('study');
}
function Boy(){
this.GF='鳳姐';
}
Boy.prototype=new Student();
Boy.prototype.constructor=Boy;
Boy.prototype.play= function () {
console.log('王者榮耀');
}
var b=new Boy()
console.log(b);
</script>
存在問(wèn)題:無(wú)法向父構(gòu)造函數(shù)傳遞參數(shù)。
共享問(wèn)題垮卓。
(4)借用構(gòu)造函數(shù)(經(jīng)典繼承)
函數(shù)的創(chuàng)建:a.直接聲明垫桂,
b.函數(shù)表達(dá)式(匿名式,命名式【使用命名式創(chuàng)建函數(shù)后粟按,關(guān)鍵字后function后的名稱只提供給內(nèi)部調(diào)用】)
c.使用構(gòu)造函數(shù)創(chuàng)建 var fuc = new function(形參1诬滩,形參2,函數(shù)體)
<script>
function Person(name,age){
//this值得是Person的實(shí)例對(duì)象
this.name = name;
this.age = age;
}
new Person();
Person.prototype.showName = function(){
console.log(this.name);
}
function Man(GF,name,age)
{
this.GF = GF;
//調(diào)用Person函數(shù),并且綁定Person函數(shù)內(nèi)部的this為第一個(gè)參數(shù),也就是Man的實(shí)例對(duì)象,也就是this
//獲得父構(gòu)造函數(shù)中的實(shí)例對(duì)象的實(shí)例成員并且傳遞參數(shù)
Person.call(this,name,age);
}
Man.prototype = new Person();
var m1 = new Man("范冰冰","小米",12);
var m2 = new Man("李冰冰","小麥",21);
//要求:m1要能夠擁有父構(gòu)造函數(shù)(Person)的實(shí)例對(duì)象上面的實(shí)例成員 和原型成員
console.log(m1);
console.log(m2);
<script>
(5)組合繼承1(原型式+借用構(gòu)造函數(shù))
<script>
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.showName = function(){
console.log(this.name);
}
function Man(GF,name,age)
{
this.GF = GF;
Person.call(this,name,age);
}
Man.prototype = Person.prototype;
var m1 = new Man("范冰冰","小米",12);
console.log(m1);
m1.showName();
</script>
依然會(huì)存在共享的問(wèn)題钾怔,需要使用深拷貝解決碱呼。
(6)組合繼承2(深拷貝+借用構(gòu)造函數(shù))
function deepcopy(obj,obj1){
obj=obj||{};
for(var key in obj1){
if(typeof obj1[key]=='object'){
obj[key]={};
deepcopy(obj[key],obj1[key])
}else{
obj[key]=obj1[key]
}
}
}
function Person(name,age){
this.name = name;
this.age = age;
}
Person.prototype.eat = function(){
console.log(this.name);
}
function Man(GF,name,age)
{
this.GF = GF;
Person.call(this,name,age);
}
deepcopy(Person.prototype,Man.prototype);
var m1 = new Man("范冰冰","小米",12);
console.log(m1);