原型对象

100 阅读2分钟

原型对象

问题

最大的问题:共享的本性导致的。

一个属性如果包含引用类型值,原型对象上的改属性修改的话,会导致所有实例的改属性变化。

function Person(){
}

Person.prototype = {
  constructor: Person,
  name: 'wang',
  age: 18,
  friends: ['Tom', 'Jack'], // 引用数据类型
  sayName: function(){
    alert(this.name);
  }
}

var person1 = new Person();
var person2 = new Person();

person1.friends.push('May');

console.log(person1.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person2.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person1.friends === person2.friends)// true

组合使用构造函数模式和原型模式 (最常用的模式)

最常见的组合 构造函数模式+原型模式

构造函数模式:用于定义实例属性

原型模式:用于定义方法和共享属性

function Person(name, age){
  this.name = name;
  this.age = age;
  this.friends = ['Tom', 'Jack'];
}

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

var person1 = new Person();
var person2 = new Person();

person1.friends.push('May');

console.log(person1.friends); // [ 'Tom', 'Jack', 'May' ]
console.log(person2.friends); // [ 'Tom', 'Jack' ]
console.log(person1.friends === person2.friends); // false

动态原型模式

特点:把所有信息都封装进构造函数,通过在构造函数中,初始化原型(仅在必要情况下),又同时使用了构造函数和原型的优点。换句话说,可以通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

缺点:不能使用对象字面量重写原型,如果在已经构建实例的情况下重写,会切断现有实例和新原型之间的联系。

function Person(name, age){
  // 属性
  this.name = name;
  this.age = age;
  this.friends = ['Tom', 'Jack'];

  // 方法
  if(typeof this.sayName != 'function'){
    Person.prototype.sayName = function(){
      alert(this.name);
    }
  }
}

寄生构造函数模式

基本思想:创建一个函数,该函数作用仅仅是封装创建对象的代码,然后再返回新的对象;很像典型的构造函数。(其实和工厂函数一模一样)。

例子:

function Person(name, age){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.sayName = function () {
    console.log(this.name);
  }

  return o;
}

var person1 = new Person('wang', 18);
person1.sayName()

假如我们想给数组加一个特殊的方法,不能直接去改Array的构造函数,可以用这个模式实现:

function SpecialArray(...args) {
  // 创建数组
  var values = new Array();
  // 添加值
  values.push.apply(values, args);
  // 添加方法
  values.toPipedString = function () {
    return this.join('+')
  }

  // 返回数组
  return values;
}

var animals = new SpecialArray('dog','pig','cat');
console.log(animals.toPipedString());

寄生构造函数模式,返回的对象与构造函数或者构造函数的原型属性之间没有关系。不能依赖instanceof操作符确定对象类型。不要使用这种模式

稳妥构造函数模式

稳妥对象:没有公共属性,而且其方法也不引用this的对象。

与寄生模式类似,instanceof 操作符对这种对象也没有意义。

function Person(name, age){
  var o = new Object();
 
  o.sayName = function () {
    console.log(name);
  }

  return o;
}

var person1 = Person('wang', 18);
person1.sayName()

非常安全,除了sayName()方法外,没有别的方式可以访问其数据成员。