js原型和繼承

原型

一、原型的概念

執(zhí)?構(gòu)造函數(shù)代碼時, js系統(tǒng)會給這個構(gòu)造函數(shù)創(chuàng)建?個原型對象,構(gòu)造函數(shù)中也包含?個prototype屬性指向這個原型對象。
原型的作用:通過原型給系統(tǒng)構(gòu)造函數(shù)添加?些特殊的?法,(如:數(shù)組元素求和)這樣通過Array創(chuàng)建出的對象都具備了這個?法。
通過原型給?定義的構(gòu)造函數(shù)添加屬性、?法,創(chuàng)建出來的對象所對應(yīng)的屬性、?法就是原型中的屬性、?法,不需要新開辟內(nèi)存空間,節(jié)約了內(nèi)存。

二、原型相關(guān)屬性、函數(shù)

原型屬性:通過原型添加在構(gòu)造函數(shù)中的屬性;
原型方法:通過原型添加在構(gòu)造函數(shù)中的函數(shù);
實例屬性:直接寫在構(gòu)造函數(shù)中的屬性;
實例方法:直接寫在構(gòu)造函數(shù)中的函數(shù)。

三、proto/[[prototype]]、constructor、prototype?個屬性的含義

proto:實例對象中的原型屬性,指向創(chuàng)造他的構(gòu)造函數(shù)對應(yīng)的原型對象(我們?法訪問到這個屬性)。

image.png

constructor:構(gòu)造函數(shù)所對應(yīng)的原型對象中的?個屬性,?來指向這個對象所對應(yīng)的構(gòu)造函數(shù)。
構(gòu)造函數(shù)創(chuàng)建出來的對象也有這個屬性,同樣指向該對象的構(gòu)造函數(shù)。
prototype:構(gòu)造函數(shù)中的?個屬性,指向他所對應(yīng)的原型對象。

四、in和hasOwnProperty方法

//in運算符:只要該對象能訪問到指定屬性,都會返回true
console.log('gender' in per2);
//每創(chuàng)建出來的對象都具備hasOwnproperty()方法,該方法可以驗證指定屬性是否是該對象(實例)
//自己維護的屬性
console.log(per2.hasOwnProperty('gender'));

繼承

一、繼承的概念

通過?個類(?類、?構(gòu)造函數(shù))創(chuàng)建出另?個類(?類、?構(gòu)造函數(shù)),這樣新創(chuàng)建出來的類不僅擁有了原有類的屬性、?法,?且還可以添加??獨有的屬性、?法,?類也可以重寫?類的?法。

二、通過call和apply實現(xiàn)繼承(“借?構(gòu)造函數(shù)”實現(xiàn)繼承)

call和apply是Function的原型?法,可以被?來調(diào)?函數(shù),他們有的第?個參數(shù)表示被調(diào)函數(shù)內(nèi)部this指針的指向?qū)ο?,剩下的參?shù)表示被調(diào)函數(shù)所需的參數(shù),apply第?個參數(shù)是?個數(shù)組,數(shù)組元素表示被調(diào)函數(shù)所需參數(shù)。

//call方法
            function hello(a,b){
                console.log(a);
                console.log(b);
                console.log(this);
            }
//通過call方法驅(qū)動函數(shù)執(zhí)行,如果call方法中第一個參數(shù)是對象,則該函數(shù)中的this指針就會
//指向這個對象,第二個參數(shù)才是函數(shù)的形參.
            hello.call(document,12,'ww');
            
//call函數(shù)通常用來修改this指針的指向,該函數(shù)需要兩類參數(shù),第一類參數(shù)是要修改指針指向
//的新對象 ,該參數(shù)只有一個,為對象類型的數(shù)據(jù),放在實參列表的第一個位置;第二類參數(shù)
//是被調(diào)用函數(shù)所需要的形參,一次在第一個參數(shù)后按順序給被調(diào)函數(shù)傳參。
            
//apply,第二個參數(shù)用[]栝起來
            hello.apply(document,[12,'ww']);

三、js中的繼承

function CreateAnimal(name,age){
                this.name=name;
                this.age=age;
                this.sayHi=function(){
                    alert('dzh');
                }
            }
            
            function CreateDog(name,age,gender){
//通過繼承獲取到另一個構(gòu)造函數(shù)中的屬性、方法(從父類中獲取數(shù)據(jù))
                CreateAnimal.call(this,name,age);
                this.gender=gender;
                this.eatFood=function(){
                    alert('kft');
                }
            }
//new關(guān)鍵字開辟一段名叫dog1的內(nèi)存空間,并將這段內(nèi)存空間的首地址返回出來,通過接收
//返回值的變量來訪問這段內(nèi)存空間。傳遞三個形參到CreateDog構(gòu)造函數(shù)中,在CreateDog
//中通過使用call繼承CreateAnimal的屬性,CreateDog和CreateAnimal中的this指代的是名為dog1
//的內(nèi)存空間。call和apply不能拿到父類原型屬性.
            var dog1=new CreateDog('ah',12,'g');
            console.log(dog1);

四、原型鏈實現(xiàn)繼承

function Parent(name) {
this.name = name;
this.say = function () {
alert("hello");
}
}
function Child(age) {
this.age = age;
}
// 通過?類的原型指針,從?類繼承相關(guān)的屬性、?法:讓?類的原型指針指向?類對象
Child.prototype = new Parent(‘張三’);
// 因為prototype中還包含?個constructor屬性,這個屬性?來指向prototype所在的構(gòu)造函數(shù),
//所以要把constructor指向的構(gòu)造函數(shù)改回Child,保證從該函數(shù)創(chuàng)建出的對象的constructor
//屬性不會指向Parent。
Child.prototype.constructor = Child;
var child = new Child(23);
alert(child.age);
child.say();

五、組合方式實現(xiàn)繼承

// 使?組合?式實現(xiàn)繼承原理:屬性使?Call繼承?式,?法使?原型鏈?式
// ?類
function Person(name) {
this.name = name;
}
Person.prototype.say = function () {
alert("my name is"+this.name);
}
// ?類
function Child(name,age) {
Person.call(this, name);
this.age = age;
}
// 先繼承?類的?法:?類的prototype指向?類的對象
Child.prototype = new Person();
// 然后添加??的新?法
Child.prototype.cry = function () {
alert("哭了");
}
var child1 = new Child("baby",23);
// child1.say();
// child1.cry();
// 驗證?類對象的構(gòu)造函數(shù)是否指向Child
console.log(child1.constructor == Child); // 沒有指向,說明繼承結(jié)構(gòu)出問題了,需
要修改
child1.constructor = Child;
console.log(child1.constructor == Child)

六、通過冒充調(diào)??式實現(xiàn)繼承

<script type="text/javascript">
// ?類
function ClassA(sColor) {
this.color = sColor;
this.show = function () {
alert(this.color);
}
}
var cA = new ClassA("red");
cA.show();
// ?類
function ClassB(sColor,age) {
// 通過冒充實現(xiàn)?類繼承?類的?法、屬性
this.newFn = ClassA; // 給this添加?個新的函數(shù),也就是ClassA這個構(gòu)造函數(shù)
this.newFn(sColor); // 執(zhí)?新添加進去的函數(shù),通過this.newFn調(diào)?ClassA,進?修改了ClassA中this指針的指向
delete this.newFn; // 修改完指針的指向后,就可以把新添加的這個?法刪掉(過河拆橋)
// 繼續(xù)添加新屬性\?法
this.age = age;
}
var cB = new ClassB("green", 23);
cB.show();
console.log(cB.age);
</script>
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

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

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