JavaScript...原型與繼承中的原型鏈...

原型

原型是什麼

在JavaScript中 函數是一個包含屬性和方法的Function類型的對象 而原型(Prototype)就是Function類型對象的一個屬性
在函數定義時就包含了prototype屬性 它的初始值是一個空對象 在JavaScript中並無定義函數的原型類型 因此原型能夠是任何類型
原型是用於保存對象的共享屬性和方法的 原型的屬性和方法並不會影響函數自己的屬性和方法數組

// Function類型的屬性 -> 全部函數都具備的屬性
console.log(Function.prototype);
// 定義函數
function fn(){
    console.log('this is function');
}
// 原型的默認值是空對象
console.log(fn.prototype);
// 函數包含構造函數 -> 全部引用類型其實都是構造函數
console.log(Number.prototype);

console.log(Object.prototype);

var result = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');
console.log(result);

獲取原型

function fn(){
    console.log('this is function');
}
// 使用訪問對象的屬性語法結構
console.log(fn.prototype);
console.log(fn['prototype']);
// Object類型提供getPrototypeOf()方法
console.log(Object.getPrototypeOf(fn));

爲原型新增屬性或者方法

function fn(){
    console.log('this is function');
}
// 變量proto也是一個空對象
// var proto = fn.prototype;

// 新增屬性或方法
// proto.name = '張三';
fn.prototype.name = '張三';
console.log(fn.prototype);
// defineProperty()
Object.defineProperty(fn.prototype, 'age', {
    value : 28,
    enumerable : true
});
console.log(fn.prototype);

構造函數的原型

// 定義構造函數
function Hero(){
    this.name = '張三';
    this.sayMe = function(){
        console.log('this is function');
    }
}
// 操做構造函數Hero的原型
Hero.prototype.age = 28;
// 利用構造函數來建立對象
var hero = new Hero();
console.log(hero);
// 爲構造函數的原型新增的屬性 -> 構造函數建立的對象中依舊能夠訪問
console.log(hero.age);// 28
// 對象hero中不存在age屬性
var result = Object.getOwnPropertyDescriptor(hero, 'age');
console.log(result);

原型屬性

自有屬性與原型屬性

自有屬性:經過對象的引用添加的屬性 其餘對象可能無此屬性 即便有 也是彼此獨立的屬性
原型屬性:從原型對象中繼承來的屬性 一旦原型對象中屬性值改變 全部繼承該原型的對象屬性均改變函數

// 定義構造函數
function Hero(name){
    // 構造函數自己的屬性 -> 自有屬性
    this.name = name;
    this.sayMe = function(){
        console.log('this is function');
    }
}
// 經過構造函數Hero的prototype新增屬性或方法
// 經過原型所定義的屬性 -> 原型屬性
Hero.prototype.age = 28;
/*
    經過構造函數Hero建立對象時
    * 不只具備構造函數的自有屬性
    * 還具備構造函數的原型屬性
 */
var hero = new Hero('張三');

console.log(hero.name);// 張三
console.log(hero.age);// 18

var hero2 = new Hero('李四');
console.log(hero2.name);// 李四
console.log(hero2.age);// 28
// 爲對象hero新增age屬性
// hero.age = 80;
// console.log(hero.age);// 80
//
// console.log(hero);
//
// console.log(hero2.age);// 28

Hero.prototype.age = 80;

console.log(hero.age);
console.log(hero2.age);

重寫屬性

經過構造函數或對象的自有屬性能夠重寫原型的屬性學習

// 定義構造函數
function Hero(){
    this.name = '張三';
}
// 構造函數的原型
Hero.prototype.name = '李四';
// 構造函數建立對象
var hero = new Hero();
// 自有屬性與原型屬性同名時,默認訪問的是自有屬性 -> 自有屬性的優先級別高於原型屬性
console.log(hero.name);// 張三

// 刪除對象的屬性
delete hero.name;
// 從新訪問對象的屬性
console.log(hero.name);// 李四

檢測原型屬性

function Hero(){
//this.name = '張三';// 自有屬性
}
 //Hero.prototype.name = '李四';

var hero = new Hero();
/*
    Object.hasOwnProperty(prop)方法
    * 做用 - 判斷當前指定屬性是否爲自有屬性
    * 參數
      * prop - 表示指定屬性名稱
    * 返回值 - 布爾值
      * true - 表示存在指定的自有屬性
      * false - 表示不存在指定的自有屬性
 */
// console.log(hero.hasOwnProperty('name'));// true
/*
    使用in關鍵字檢測對象的屬性
    * 做用 - 判斷對象中是否存在指定屬性(自有屬性或原型屬性)
    * 返回值 - 布爾值
      * true - 表示存在指定的屬性
      * false - 表示不存在指定的屬性
 */
console.log('name' in hero);

操做原型的方式

// 定義構造函數
function Hero(){}
// 經過構造函數的原型新增屬性或方法

// 1.利用對象.屬性或方法的方式新增屬性或方法
Hero.prototype.name = '張三';
Hero.prototype.sayMe = function(){
    console.log('this is function');
}
// 2.將原型從新賦值爲一個新對象
Hero.prototype = {
    name : '張三',
    sayMe : function(){
        console.log('this is function');
    }
}

// 經過構造函數建立對象
var hero = new Hero();

console.log(hero.name);
hero.sayMe();

顯式原型與隱式原型

// 定義構造函數
function Hero(){
    this.name = '張三';
}
// 經過構造函數的原型新增屬性或方法
Hero.prototype.age = 28;
// 經過構造函數建立對象
var hero = new Hero();

console.log(hero.name);// 對象調用自有屬性
console.log(hero.age);// 對象調用原型屬性

/*
    全部對象其實也具備原型
    * 注意 - 對象的原型(__proto__)並不是是函數的原型(prototype)
    * 區分
      * 將函數的原型 -> 顯式原型
      * 將對象的原型 -> 隱式原型
    * 對象的原型
      * 不能用於真實開發工做,僅用於邏輯測試
 */
console.log(hero.prototype);// undefined 表示對象中不存在該屬性
console.log(hero.__proto__);

isPrototypeOf()方法

每一個對象中都會具備一個isPrototypeOf()方法 該方法用來判斷一個對象是不是另外一個對象的原型測試

// 經過初始化器方式定義對象
var obj = {
    name : '張三'
}
//定義構造函數
function Hero(){}
//將對象obj賦值給構造函數Hero的原型
Hero.prototype = obj;
//經過構造函數建立對象
var hero = new Hero();
//判斷指定對象是不是另外一個對象的原型
var result = obj.isPrototypeOf(hero);

console.log(result);

擴展內置對象

JavaScript中的內置對象有些也具備prototype屬性 利用內置對象的prototype屬性能夠爲內置對象擴展屬性或方法
經過原型擴展內置對象的屬性和方法很是靈活 根據個性化要求制定Java Script語言的具體內容this

Object.prototype.sayMe = function(){
    console.log('this is sayMe function');
}
// 經過Object構造函數建立對象
var obj = new Object();

obj.sayMe();


Array.prototype.inArray = function(color){
    // this - 表示當前的數組
    for(var i = 0, len = this.length; i < len; i++){
        if(this[i] === color){
            return true;
        }
    }
    return false;
}
var arr = ["red", "green", "blue"];

console.log(arr.inArray("red")); //true
console.log(arr.inArray("yellow")); //false

繼承

原型鏈是什麼

構造函數或構造器具備prototype屬性 對象具備__proto__屬性 這就是以前學習的原型
若是構造函數或對象A A的原型指向構造函數或對象B B的原型在指向構造函數或對象C 以此類推 最終的構造函數或對象的原型指向Object的原型 由此造成一條鏈狀結構 被稱之爲原型鏈
按照上述的描述 在B中定義的屬性或方法 能夠直接在A中使用並不須要定義 這就是繼承 它容許每一個對象來訪問其原型鏈上的任何屬性或方法prototype

// 原型鏈
function A(){
    this.a = 'a';
}
// 經過構造函數建立對象
var a = new A();

function B(){
    this.b = 'b';
}
// 將B的原型指向對象a
B.prototype = a;
// 經過構造函數建立對象
var b = new B();

console.log(b.b);// b
console.log(b.a);// a

function C(){
    this.c = 'c';
}
// 將C的原型指向對象b
C.prototype = b;
// 經過構造函數建立對象
var c = new C();

console.log(c.c);// c
console.log(c.b);// b
console.log(c.a);// a

只繼承於原型

處於對效率的考慮 儘量地將屬性和方法添加到原型上
1.不要爲繼承關係單首創建新對象
2.儘可能減小運行時的方法搜索code

// 原型鏈
function A(){
    // 將自有屬性改寫爲原型屬性
    // this.a = 'a';
}
A.prototype.a = 'a';

function B(){
    // this.b = 'b';
}

// 將B的原型指向
B.prototype = A.prototype;

B.prototype.b = 'b';
/*B.prototype = {
    b : 'b'
}*/

function C(){
    this.c = 'c';
}
// 將C的原型指向
C.prototype = B.prototype;

var c = new C();
console.log(c.c);// c
console.log(c.b);
console.log(c.a);// a

原型鏈實現繼承的問題

// 原型鏈
function A(){
    // 將自有屬性改寫爲原型屬性
    // this.a = 'a';
}
A.prototype.a = 'a';

function B(){
    // this.b = 'b';
}

// 將B的原型指向
B.prototype = A.prototype;

B.prototype.b = 'b';

function C(){
    // this.c = 'c';
}
// 將C的原型指向
C.prototype = B.prototype;
C.prototype.c = 'c';

var c = new C();
console.log(c.c);// c
console.log(c.b);// b
console.log(c.a);// a

var a = new A();

console.log(a.a);
console.log(a.b);
console.log(a.c);

var b = new B();

console.log(b.a);
console.log(b.b);
console.log(b.c);
相關文章
相關標籤/搜索