什么是原型模式

使用构造函数的 prototype 属性来指定那些应该共享的属性和方法。组合使用构造
函数模式和原型模式时,使用构造函数定义实例属性,而使用原型定义共享的属性和方法。

function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
person1.sayName(); //"Nicholas"
var person2 = new Person();
person2.sayName(); //"Nicholas"
alert(person1.sayName == person2.sayName); //true

理解原型对象

实例(指针)->构造函数constructor属性->prototype属性->原型对象

  • Object.getPrototypeOf() ,在所有支持的实现中,这个

方法返回 [[Prototype]] 的值。

alert(Object.getPrototypeOf(person1) == Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"
  • 当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性
function Person(){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
person1.name = "Greg";
alert(person1.name); //"Greg"——来自实例
alert(person2.name); //"Nicholas"——来自原型
delete person1.name;
alert(person1.name); //"Nicholas" ——
  • 使用 hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。属性存在于对象实例中时,才会返回 true 。
function Person() {
}
Person.prototype.name = "Nicholas";
Person.prototype.age = 29;
Person.prototype.job = "Software Engineer";
Person.prototype.sayName = function () {
    alert(this.name);
};
var person1 = new Person();
var person2 = new Person();
alert(person1.hasOwnProperty("name")); //false
person1.name = "Greg";
alert(person1.name); //"Greg"——来自实例
alert(person1.hasOwnProperty("name")); //true
alert(person2.name); //"Nicholas"——来自原型
alert(person2.hasOwnProperty("name")); //false
delete person1.name;
alert(person1.name); //"Nicholas"——来自原型
alert(person1.hasOwnProperty("name")); //false

原型与in操作符

使用 in 操作符, in 操作符会在通过对象能够访问给定属性时返回 true ,无论该属性存在于实例中还是原型中。

结合使用in和hasPrototypeProperty()可以确定属性到底是存在对象中还是原型中

function hasPrototypeProperty(object, name){
    return !object.hasOwnProperty(name) && (name in object);
}

更简单的原型语法

为减少不必要的输入,也为了从视觉上更好地封装原型的功能,更常见的做法是用一个包含所有属性和方法的对象字面量来重写整个原型对象.

function Person() {
}
Person.prototype = {
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function () {
        alert(this.name);
    }
};
// 重设构造函数,只适用于 ECMAScript 5  兼容的浏览器
Object.defineProperty(Person.prototype, "constructor", {
    enumerable: false,
    value: Person
});

原型的动态性

由于在原型中查找值的过程是一次搜索,因此我们对原型对象所做的任何修改都能够立即从实例上反映出来——即使是先创建了实例后修改原型也照样如此。(但是重写整个原型是不行的,因为切断了构造函数与最初原型的联系)

var friend = new Person();
Person.prototype.sayHi = function(){
alert("hi");
};
friend.sayHi(); //"hi"(没有问题!)

原型对象的问题

  • 构造函数指向需要手工写入
  • 对于引用类型来说有共享问题的错误

Wheeler
19 声望0 粉丝

今天,你学习了吗?