免费视频淫片aa毛片_日韩高清在线亚洲专区vr_日韩大片免费观看视频播放_亚洲欧美国产精品完整版

打開APP
userphoto
未登錄

開通VIP,暢享免費電子書等14項超值服

開通VIP
筆記:《JavaScript面向?qū)ο缶?/div>

第5章 繼承

5.1原型對象鏈和Object.prototype

原型對象鏈:對象繼承其原型對象,而原型對象繼承他的原型對象,以此類推。
原型對象的屬性可經(jīng)由對象實例訪問。
所有對象都繼承自O(shè)bject.prototype。任何以對象字面形式定義的對象,其[[Prototype]]的值都被設(shè)為Object.prototype。

5.1.1 繼承自O(shè)bject.prototype的方法

hasOwnProperty() 檢查是否存在一個給定名字的自有屬性

propertyIsEnumerable() 檢查一個自有屬性是否可枚舉

isPrototypeOf() 檢查一個對象是否是另一個對象的原型對象

valueOf() 返回一個對象的值表達(dá)
valueof()默認(rèn)返回對象實例本身。原始封裝類型重寫了valueOf() 以使得它對String返回字符串,對Boolean返回一個布爾值,對Number返回一個數(shù)字。

toString() 返回一個對象的字符串表達(dá)
一旦valueOf返回的是一個引用而不是原始值的時候,就會回退調(diào)用toString() 方法。
//使用加號時,一邊是字符串,另一邊會轉(zhuǎn)換成字符串
1+'2';    //12

//如果另外一邊是原始值,會自動轉(zhuǎn)換成字符串表達(dá)式
true+'2';   //true2
true+2;     //3
//如果另一邊是引用類型,則會調(diào)用valueOf();如果valueOf()返回一個引用值,則調(diào)用toString()
//以下例子,book先調(diào)用了valueOf(),然后回退調(diào)用了toString();array只調(diào)用了valueOf()
var book = {
    title:'Hello world'
};
var array = [2,3,5];

book+'2';   //[object Object]2
array+'2';    //2,3,52
array+2;    //2,3,52

book.valueOf();    //{title: 'Hello world'}
book.toString();    //[object Object]
  因為book是一個對象,其方法繼承自O(shè)bject.prototype,大部分JavaScript引擎返回默認(rèn)值'[object Object]'。我們可以定義自己的toString()方法,來為此類字符串轉(zhuǎn)換提供包含更多信息的值。
var book = {
    title: 'Hello world',
    toString: function(){
        return '[Book: ' +this.title + ']';
    }
};

var person = {
    name:'liang'
};

book+'2';        //[Book: Hello world]2
person+'2';        //[object Object]2

5.1.2 修改Object.prototype

由于所有對象都默認(rèn)繼承自O(shè)bject.prototype,所以修改這個屬性將影響到所有的對象。
而且,會給Object.prototype添加可枚舉屬性,隨著for-in循環(huán)的頻繁使用,影響到大量代碼。
因此,最好不要修改或添加Object.prototype。
Object.prototype.add = function(value){
    return this + value;
};

var person = {
    name:'liang'
};

console.log(person.add(' cool'));    //[object Object] cool
console.log(document.add(true));    //[object HTMLDocument]true
console.log(window.add(5));    //[object Window]5
如果有添加比較多的Object.prototype屬性,在for-in中應(yīng)該使用hasOwnProperty()排除掉這些繼承來的屬性。
Object.prototype.add = function(value){
    return this + value;
};

var person = {
    name:'liang'
};

for(var property in person){
    if (person.hasOwnProperty(property)){
        console.log(property);
    }
}        //name

5.2 對象繼承

對象字面形式會隱式指定Object.prototype為其[[Prototype]]。
可以用Object.create()方法顯式指定要繼承哪個原型對象。
Object.create() 方法接受兩個參數(shù):一個需要被設(shè)置為新對象的[[Prototype]]、一個屬性描述對象(可選)。
var book = {
    title: 'Hello world'
};

//上下兩例效果相同

var book = Object.create(Object.prototype,{
    title: {
        configurable: true,
        enumerable: true,
        value: 'Hello world',
        writable: true
    }
});

讓一個對象繼承另一個對象的屬性。
var person1 = {
    name: 'liang',
    sayName: function(){
        console.log(this.name);
    }
};

var person2 = Object.create(person1,{
    name:{
        configurable: true,
        enumerable: true,
        value: 'zhu',
        writable: true
    }
});

person1.sayName();    //liang
person2.sayName();    //zhu

console.log(person1.isPrototypeOf(person2));    //true
console.log(person2.hasOwnProperty('sayName'));    //false
sayName() 依然只存在于person1并被person2繼承。
person2繼承自person1,person1繼承自O(shè)bject.prototype。
當(dāng)訪問一個對象的屬性時,JavaScript引擎會執(zhí)行一個搜索過程,先搜索對象實例(如person2),然后繼續(xù)搜索[[Prototype]],直到繼承鏈末端。末端的[[Prototype]]被置為null。

可創(chuàng)建[[Prototype]]為null的對象,創(chuàng)建出一個沒有原型對象的對象。
var obj1= Object.create(null);
var obj2 = {};

console.log('toString' in obj1);    //false
console.log('toString' in obj2);    //true
obj1此時是一個沒有任何預(yù)定義屬性的白板,成為了一個完美的哈希容器,因為不會跟繼承來的屬性名字起沖突。

5.3 構(gòu)造函數(shù)繼承

對象繼承是構(gòu)造函數(shù)繼承的基礎(chǔ)。
幾乎所有函數(shù)都有prototype屬性,可以被修改。
泛用對象的prototype屬性被自動設(shè)置為繼承自O(shè)bject.prototype,該對象有一個自有屬性constructor。
可以改寫prototype屬性來改變原型對象鏈。
//創(chuàng)建長方形的構(gòu)造函數(shù),并添加、修改protype屬性
function Rectangle(length,width){
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function(){
    return this.length * this.width;
};

Rectangle.prototype.toString = function(){
    return '[Rectangle ' + this.length + 'x' + this.width + ']';
};

//創(chuàng)建正方形的構(gòu)造函數(shù),并使之繼承長方形的prototype屬性
function Square(size){
    this.length = size;
    this.width = size;
}


Square.prototype = new Rectangle();  //此處將Square.prototype改寫為一個Rectangle對象

//因為Square繼承了Rectangle的屬性constructor,添加下一行代碼來恢復(fù)原值                                                                    
Square.prototype.constructor = Square;                                                                                                

var rect = new Rectangle(5,10);    
var squa = new Square(5);    

console.log(rect.getArea());    //50
console.log(squa.getArea());    //25

console.log(rect.toString());    //[Rectangle 5x10]
console.log(squa.toString());    //[Rectangle 5x5]

//Square繼承來的toString要重新設(shè)定,使它符合需要;也可以用call()或apply()方法,具體見5.5訪問父類方法
Square.prototype.toString = function(){
    return '[Square ' + this.length + 'x' + this.width + ']';
}

console.log(squa.toString());    //[Square 5x5]

//最后,檢測繼承的原型 注:instanceof寫成instanceOf,會報錯'missing ) after argument list'
console.log(rect instanceof Rectangle);    //true
console.log(rect instanceof Object);    //true

console.log(squa instanceof Square);    //true
console.log(squa instanceof Rectangle);    //true
console.log(squa instanceof Object);    //true
Square.prototype并不真的需要改寫為一個Rectangle對象,要的只是把Square.prototype指向Rectangle.prototype。
因此,可以用Object.create()改寫上述例子。
//...Rectangle的構(gòu)造函數(shù)...
function Square(size){
    this.length = size;
    this.width = size;
}
//下面讓Square.prototype繼承自Rectangle.prototype。
Square.prototype = Object.create(Rectangle.prototype,{
    constructor:{
        configurable: true,
        enumerable: true,
        value: Square,
        writable: true
    }
});

Square.ptototype.toString = function(){
    return '[Square ' + this.length + 'x' + this.width + ']';
};

5.4 構(gòu)造函數(shù)竊取

構(gòu)造函數(shù)竊取就是用自己的對象竊取父類的構(gòu)造函數(shù)。只需要在子類的構(gòu)造函數(shù)中用call() 或者apply() 調(diào)用父類的構(gòu)造函數(shù),并將新創(chuàng)建的對象傳進(jìn)去即可。
function Rectangle(length,width){
    this.length = length;
    this.width = width;
}

Rectangle.prototype.getArea = function(){
    return this.length * this.width;
};

Rectangle.prototype.toString = function(){
    return '[Rectangle ' + this.length + 'x' + this.width + ']';
};

//讓Square竊取Rectangle的構(gòu)造函數(shù)
function Square(size){
    Rectangle.call(this,size,size);    //傳入兩次size,一次作為lenth,一次作為width   
     //此處還可添加新的屬性或覆蓋已有的屬性
}

Square.prototype = Object.create(Rectangle.prototype,{
    constructor:{
        configurable: true,
        enumerable: true,
        value: Square,
        writable: true
        }
});

Square.prototype.toString = function(){
    return '[Square ' + this.length + 'x' + this.width + ']';
};

var squa = new Square(6);

console.log(squa.length);    //6
console.log(squa.width);    //6
console.log(squa.getArea());    //36
你經(jīng)常需要修改一個構(gòu)造函數(shù)的原型對象,你也經(jīng)常需要在子類的構(gòu)造函數(shù)中調(diào)用父類的構(gòu)造函數(shù)。
一般來說,需要修改prototype來繼承方法并用構(gòu)造函數(shù)竊取來設(shè)置屬性。這種做法模仿了那些基于類的語言的類繼承,所以被稱為偽類繼承。

偽類繼承的方法:使用call()繼承構(gòu)造函數(shù),使用create()繼承其prototype原型屬性并修改。

5.5 訪問父類方法

5.3與5.4的代碼中,通過設(shè)置toString() 方法隱藏了其原型對象的toString() 方法。是隱藏不是覆蓋,因為在delete后,還能調(diào)用其原型對象的toString() 方法。
下面例子,通過call() 調(diào)用父類的方法,并替換要修改的值。這是唯一訪問父類方法的手段。
//5.3與5.4中的代碼
Square.prototype.toString = function(){
    return '[Square ' + this.length + 'x' + this.width + ']';
};

//可以替換為

Square.prototype.toString = function(){
    var text = Rectangle.prototype.toString.call(this);
    return text.replace('Rectangle','Square');
};

第五章總結(jié):

JavaScript通過原型對象鏈支持繼承。當(dāng)將一個對象的[[Prototype]]設(shè)置為另一個對象時,就在這兩個對象之間創(chuàng)建了一條原型對象鏈。
所有泛用對象都繼承自O(shè)bject.prototype。如要創(chuàng)建一個繼承自其他對象的對象,使用Object.create()指定[[Prototype]]為一個新對象。
直接創(chuàng)建一條原型對象鏈在繼承其他對象的方法時工作得十分好,但你不能用原型對象繼承自有屬性。為了正確繼承自有屬性,可以使用構(gòu)造函數(shù)竊取。結(jié)合構(gòu)造函數(shù)竊取和原型對象鏈,這種組合稱為偽類繼承,是JavaScript中最常見的繼承手段。
本站僅提供存儲服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊舉報。
打開APP,閱讀全文并永久保存 查看更多類似文章
猜你喜歡
類似文章
生活服務(wù)
分享 收藏 導(dǎo)長圖 關(guān)注 下載文章
綁定賬號成功
后續(xù)可登錄賬號暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點擊這里聯(lián)系客服!

聯(lián)系客服