JavaScript 对象创建模式

一、工厂模式

function createPerson(name, age, job){
  var o = new Object();
  o.name = name;
  o.age = age;
  o.job = job;

  return o;
}

var person1 = createPerson('Jerry', 12, 'job1');
var person2 = createPerson('Tom', 13, 'job2');

这样创建的对象无法识别对象的类型(只是Object类型)

 

二、构造函数模式,

通过构造函数创建的对象,都可以标识为一种特定类型。

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.jbo = jbo;
}

var person1 = new Person('Jerry', 12, 'job1');
var person2 = new Person('Tom', 13, 'job2');

//构造函数创建的对象能识别对象类型,即:person1和person2都是Person类型的对象

console.log(person1 instanceof Person);  //true
console.log(person1 instanceof Object);  //true
console.log(person2 instanceof Person);  //true
console.log(person2 instanceof Object);  //true

//对象创建后,都有一个constructor属性指向Person
console.log(person1.constructor == Person); // true
//constructor 属性就是为了标识对象的类型,但是用constructor判断对象的类型并不一定正确,在原型链技术里会存在问题,相比来说,instanceof更可靠一些。

构造函数创建对象经过下面4个步骤:

1. 创建一个新对象

2.将构造函数的作用域赋给新对象

3.执行构造函数,给新对象添加属性

4.返回新对象

构造函数与普通函数的唯一一点区别就是调用方式的不同:构造函数用new来调用,普通函数直接调用。理论上来说,任何函数都可以是构造函数,构造函数也可以像普通函数那样直接调用

Person('Jerry', 12, 'job1');//调用后,属性会添加到window对象上,因为没有指定作用域,则作用域赋给了全局对象。
//如果想确定作用域,可以这样调用构造函数
var o = new Object();
Person.call(o, 'Jerry', 12, 'job1');

问题:使用构造函数创建对象,对象中的函数会存在多个副本,例如:

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job;
    this.sayName = function(){
        console.log(this.name);
    }
}

var person1 = new Person('Tom', 12, 'job1');
var person2 = new Person('Jerry', 13, 'job2');
console.log(person1.sayName === person2.sayName); // false

//person1 和 person2 分别拥有sayName 的副本

变种:

a、寄生构造函数

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

function SpecialPerson(name){
    var sp = new Person(name);
    sp.age = age;
    return sp;
}

var person = new SpecialPerson('Jerry');

//该方式可以拓展原类型
//这种方式最想Delphi中的继承

b,稳妥构造函数

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

//该方式最大的优点就是安全,除了sayName函数外,没有任何办法访问到原始数据。

 

 

三、原型模式

每个函数都有一个prototype属性,指向一个原型对象,构造函数创建的对象,共享原型对象。

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

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

console.log(person1.sayName === person2.sayName); // true

对象创建后,会有一个[[prototype]]属性指向原型对象;原型对象会自动获得一个constructor属性,指向Person,其它属性则直接来自Object。当调用对象的属性或者函数的时候,首先搜索对象本身,如果没有,再搜索[[prototype]]指向的原型对象(搜索算法应该是一个递归)。原型方法也可以用更方便的方式

function Person(){

}

Person.prototype = {
    name : 'Jerry',
    age : 12,
    sayName : function(){
        console.log(this.name);
    }
}

//使用字面量的方式更方便,但是有一个问题:原型对象的constructor不再指向Person,而是Object,需要手动赋值。

在原型对象中添加的属性和函数,会立即反映到实例对象上。但要注意:原型对象是在创建构造函数后就已经生成了,创建的实例对象也会指向该原型对象,如果再重新创建构造函数的原型对象,实例对象会访问不到新的原型对象。

 

四、组合使用构造函数和原型对象模式

function Person(name, age, job){
    this.name = name;
    this.age = age;
    this.job = job
}

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

组合使用构造函数和原型对象是当下使用最广泛、认同度最高的创建自定义类型的方式。
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值