JS之创建对象的方式及其优劣

一、工厂模式

    用函数来封装以特定接口创建对象的细节。

function createPerson(name,age) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.sayName = function() {
        alert(this.name);
    }
    return o;
}
var person1 = createPerson("Dobby1", 5);
var person2 = createPerson("Dobby2", 6);

优点:解决了创建多个相似对象的问题;

缺点:没有解决对象识别的问题(怎样知道一个对象的类型)。

二、构造函数模式

1. 不用显示的创建对象
2. 直接将方法和属性赋给了this对象
3. 没有return语句
4. 函数名的首字母大写
5. 必须使用 new 操作符创建新实例
6. 实例对象都有一个 constructor(构造函数)属性,该属性指向构造函数
7. 可以用 instanceof 操作符验证其类型。

function Person(name,age) {    
    this.name = name;
    this.age = age;
    this.sayName = function() {  
       alert(this.name);
    }
    return o;
}
var person1 = createPerson("Dobby1", 5);
var person2 = createPerson("Dobby2", 6);

优点:创建自定义的构造函数意味着可以将它的实例标识为一种特定的类型;

缺点:每个方法都要在每个实例上面重新创造一遍(ECMAScript中的函数是对象,因此每定义一个函数,也就是实例化了一个对象),也就是说,以这种方式创建对象,会导致不同的作用域链和标识符解析,但创建 Function 新实例的机制仍然是相同的。因此,不同实例上的同名函数第不相等的。

解决上述缺点可以通过把函数定义转移到构造函数来解决这个问题。但如果对象需要定义很多方法,那么就要定义很多个全局函数,于是我们这个自定义的引用类型就丝毫没有封装性可言了。

三、原型模式

我们创建的每个函数,都有一个 prototype(原型)属性,这个属性是一个指针,指向一个对象,该对象包含可以由特定类型的所有实例共享的属性和方法。即我们不必在构造函数中定义对象实例的信息,而将这些信息直接添加到原型对象中。

function Person() {}
Person.prototype.name = "Dobby";
Person.prototype.age = 5;
Person.prototype.sayName () = function() {
    alert(this.name);
}
var person1 = new Person();
var person2 = new Person();

优点:对象的所有属性和方法由所有实例共享,即实例访问都是同一组属性和方法;

缺点:首先,所有实例在默认情况下取得相同的属性值;最大的问题是当对象包含引用值的属性(如数组)时,如果一个实例的属性值数组发生变化,即该数组的变化将反应在所有的实例上。

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

构造函数模式用于定义实例属性,而原型模式用于定义方法和共享属性。

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

优点:每个实例都会有自己的一份实例属性的副本,但同时又共享着对方法的引用,最大限度的节省了内存,另外,这种模式还支持向构造函数传递参数;

缺点:没有把全部信息封装在构造函数中。

五、动态原型模式

可以通过检查某个应该存在的方法是否有效,来动态决定是否需要初始化原型。

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

    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() {
        alert(this.name);
     }
     return o;
}
var friend = new Person("Dobby", 5);

除了使用 new 操作符并把使用的包装函数叫构造函数之外,这个模式和工厂模式其实是一模一样的。

七、稳妥构造函数模式

没有公共属性,而且其他方法也不引用 this 对象。
与寄生构造函数有两点不同:
1. 新创建对象的实例方法不引用 this
2. 不使用 new 操作符调用构造函数

function Person(name, age) {
    var o = new Object();
    // 定义私有变量和函数

    // 添加公有方法
    o.sayName = function() {
        alert(name);
    }
    return o;
}
var friend = Person("Dobby", 5);

其安全性使它非常适合在某些安全执行环境下使用。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  •   面向对象(Object-Oriented,OO)的语言有一个标志,那就是它们都有类的概念,而通过类可以创建任意...
    霜天晓阅读 2,283评论 0 6
  • 普通创建对象和字面量创建对象不足之处:虽然 Object 构造函数或对象字面量都可以用来创建单个对象,但这些方式有...
    believedream阅读 2,633评论 2 18
  • 博客内容:什么是面向对象为什么要面向对象面向对象编程的特性和原则理解对象属性创建对象继承 什么是面向对象 面向对象...
    _Dot912阅读 1,568评论 3 12
  • 曾一度的为你付出 为的就是让你更完美 400多个白天黑夜 挥洒了莫名的汗水 这是你成长的足迹 你都在进步了 这标志...
    茕灺阅读 561评论 10 15
  • 新工作的第八周,也没什么特别的,无非是对新工作,新公司,新同事的彼此了解与熟悉。 有对新工作的憧憬,但随着时间流逝...
    阿伦影子阅读 2,028评论 0 0

友情链接更多精彩内容