首頁 > web前端 > js教程 > 詳解JavaScript中基於原型prototype的繼承特性_基礎知識

詳解JavaScript中基於原型prototype的繼承特性_基礎知識

WBOY
發布: 2016-05-16 15:02:05
原創
1557 人瀏覽過

JavaScript 中的繼承比較奇葩,無法實作介面繼承,只能靠原型繼承。

原型鏈
原型就是一個對象,透過建構函式創建出來的實例會有指針指向原型得到原型的屬性和方法。這樣,實例物件就帶有建構函式的屬性方法和原型的屬性方法,然後將需要繼承的建構函式的原型指向這個實例,即可擁有這個實例的所有屬性方法實作繼承。
看下面示範程式碼:

//声明超类,通过构造函数和原型添加有关属性和方法
function Super(){
  this.property = true;
}
Super.prototype.getSuperValue = function() {
  return this.property;
};

//声明子类的构造函数
function SubType() {
  this.subproperty = false;
}
//将子类的原型指向超类的实例,得到超类的一切
SubType.prototype = new Super();
SubType.prototype.constructor = SubType;
SubType.prototype.getSubValue = function(){
  return this.subproperty;
};
//由子类创建对象,测试是否继承超类方法和属性
var instance = new SubType();
console.log(instance.getSuperValue());

登入後複製

所有函數的預設原型都是 Object 的實例,因此預設原型都會包含一個內部指針,指向 Object.prototype。
使用 instanceof 和 isPrototypeOf 可以確定原型和實例的關係:

instance instanceof Object;
Object.prototype.isPrototypeOf(instance);
登入後複製

使用原型鏈的時候,需要謹慎的定義方法。子類別需要重寫超類型的某個方法或擴充,一定要放在替換原型的語句後面,這樣才能生效。此外,透過原型鏈實現繼承時,不能使用物件字面量來建立原型方法,這樣會重寫原型鏈:

......
SubType.prototype = new Super();
SubType.prototype = {
  ....
};
登入後複製

這會更換指針指向新對象,從而重寫了原型鏈。
原型鏈的繼承方法是有缺陷的,主要有兩個問題:
1,來自包含引用類型值的原型,會被所有實例共用。
前面文章介紹過包含引用類型值的原型屬性會被所有實例共享,一個實例修改,其他實例會隨之改變,因此需要在建構子中定義屬性。而原型鏈繼承的時候,無論超類別中屬性是在建構子或原型中定義,全部都變成了實例物件被子類別繼承,從而對子類別的實例產生影響。
2,在建立子類型的實例時,不能傳遞參數給超類型的建構子。
原型鏈的繼承,直接將子類別原型指向超類別的實例,這時候可以傳遞參數給超類別。但是當子類別建立實例的時候,只能傳遞參數給子類別的建構子參數,而不能傳遞參數給超類別的建構子。
因此在實際應用中,很少單獨使用原型鏈。

相關的一些程式碼實作

鑑別一個原型屬性

function hasPrototypeProperty(object, name) {
  return name in object && !object.hasOwnProperty(name);
}
登入後複製

在建構函式中使用原型物件

function Person(name) {
  this.name = name;
}

Person.prototype = {
  constructor: Person,
  sayName: function () {
    console.log(this.name);
  },
  toString: function() {

  }
};

var person1 = new Person('Nicholas');
var person2 = new Person('Greg);

console.log(person1 instanceof Person); // true
console.log(person1.constructor === Person); // true
console.log(person1.constructor === Object); // false

console.log(person2 instanceof Person); // true
console.log(person2.constructor === Person); // true
console.log(person2.constructor === Object); // false

登入後複製

物件繼承

var person1 = {
  name: 'Nicholas',
  sayName: function () {
    console.log(this.name);
  }
};

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

person1.sayName(); // Nicholas
person2.sayName(); // Greg

console.log(person1.hasOwnProperty('sayName')); // true
console.log(person1.isPropertyOf(person2)); // true
console.log(person2.hasOwnProperty('sayName')); // false

登入後複製

模組模式

var person = (function () {
  var age = 25;

  function getAge() {
    return age;
  }

  function growOlder() {
    age++;
  }

  return {
    name: 'Nicholas',
    getAge: getAge,
    growOlder: growOlder
  };
}());

登入後複製

作用域的建構子

function Person(name) {
  this.name = name;
}

Person.prototype.sayName = function() {
  console.log(this.name);
};

var person1 = Person('Nicholas');

console.log(person1 instanceof Person); // false
console.log(typeof person1); // undefined
console.log(name); // Nicholas

登入後複製
相關標籤:
來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板