4、原型和面向對象

實例化和原型

在JavaScript中,使用原型定義的屬性和功能會自動應用到對象的實例上,一但進行了定義,原型的屬性就會變成實例化對象的屬性。所有函數初始化的時候都有一個prototype屬性表示原型。

// 定義一個函數
function A() {}

// 在其原型上添加屬性
A.prototype.go = function () {return true;};

// 將函數賦值給變量,空函數無返回值
var a1 = A();
console.log(a1);  // undefined

// 將函數作為構造器進行實例化賦值給變量
var a2 = new A();

// 變量成為一個實例
console.log(a2); // A {}

// 該實例繼承了函數原型上的屬性
console.log(a2.go()); // true

使用new操作符將函數作為構造器進行調用時,其上下文會被定義為新對象實例。這就表明,在構造器函數內部,可以使用this參數初始化值。在構造器內的綁定操作優先級會高于在原型上的綁定操作優先級,因為構造器的this上下文指的是實例自身。

// 使用同樣的名稱為構造器和原型添加屬性
function A() {
    this.x=1;
}
A.prototype.x = 2;

// 實例繼承屬性時,構造器本身的屬性會覆蓋原型上的屬性
var a1 = new A();
console.log(a1.x);  // 1

原型的改變會影響其構造器已經創建的實例對象。

// 創建構造函數并實例化
function A() {}
var a1 = new A();

// 改變其原型,已經實例化的對象上繼承的屬性也會被修改
A.prototype.x = 1;
console.log(a1.x);

每個JavaScript對象都有一個隱式屬性constructor,該屬性引用的是創建該對象的構造器。

function A() {}
var a1 = new A();
A.prototype.x = 1;
// 使用a1.constructor.prototype.x可以訪問到原型上的x屬性,證明了原型是實時附加在對象上的,所以在創建實力之后,更改原型也會生效。
console.log(a1.constructor.prototype.x);  // 1

查找屬性時,首先查找對象自身,如果沒有找到,再查找構造器的原型。

function A() {
    this.x=1;
    this.y=2;
}
var a1 = new A();
A.prototype.y=1;
// 實例化的對象a1已經具有了y屬性,即使在實例化之后再為構造器的原型添加新的y屬性,也不會覆蓋實力中的原來的y屬性。
console.log(a1.y);  // 2

利用constructor屬性,可以在不知道原有構造器的情況下,利用已有的實例來創建新的實例。

function A() {}
var a1 = new A();
var a2 = new a1.constructor();
// a1與a2指向的不是同一個實例
console.log(a1 !== a2); // true

疑難陷阱

擴展原生Object.prototype時,所有對象都會接受這些額外的屬性。當我們遍歷對象的屬性時,這些額外的屬性也會被遍歷。

// 為原生Object.prototype添加keys方法,返回一個屬性名組成的數組。
Object.prototype.keys=function () {
    var key = [];
    for(var p in this){
        key.push(p);
    }
    return key;
};
var obj = {
    a:1,
    b:2,
    c:3
};
// keys方法本身被繼承,也成為了實例obj的屬性之一
console.log(obj.keys());  // ["a", "b", "c", "keys"]

使用hasOwnProperty()方法可以判斷屬性是實例自身的,還是繼承自原型的

Object.prototype.keys=function () {
    var key = [];
    for(var p in this){
        // 判斷屬性是來自實例自身還是繼承自原型
        if(this.hasOwnProperty(p)){
            key.push(p);
        }
    }
    return key;
};
var obj = {
    a:1,
    b:2,
    c:3
};
console.log(obj.keys()); // ["a", "b", "c"]
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容