`
MirrorAvatar
  • 浏览: 48417 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

批量创建ECMAScript对象的七种模式

阅读更多

创建单个对象的方法:

  1. 直接量

    var blog = {
        author: "MirrorAvatar",
        year: 2015
    };
  2. 关键字new

    var blog = new Object();
    blog.author = "MirrorAvatar";
    blog.year = 2015;

以上方法的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为了可复用性,才有了下面七种用于批量创建对象的七种模式。

1.工厂模式(Factory Pattern)

 
function createPerson(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    };
    return o;
}

var person1 = createPerson("MirrorAvatar", "3", "coder");
var person2 = createPerson("Cindy", "4", "master");

console.log(person1);  //Object {name: "MirrorAvatar", age: "3", job: "coder", sayName: function}
console.log(person2); //Object {name: "Cindy", age: "4", job: "master", sayName: function}
 

代码特点:

  • 函数名首字母小写
  • 可以传入参数
  • 函数显式地创建并返回一个对象
  • 解决了创建多个相似对象的问题

缺点:无法识别一个对象的类型

2.构造函数模式(Constructor Pattern)

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

var person1 = new Person("MirrorAvatar", "3", "coder");
var person2 = new Person("Cindy", "4", "MLer");

console.log(person1);  //Person {name: "MirrorAvatar", age: "3", job: "coder", sayName: function}
console.log(person2);  //Person {name: "Cindy", age: "4", job: "MLer", sayName: function}
 

代码特点:

  • 函数名首字母大写,为区分普通函数
  • 直接将属性和方法赋值给this对象
  • 没有return语句
  • 创建Person对象实例,必须使用new操作符

创建构造函数实例的过程:

  1. 创建一个新对象;
  2. 将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
  3. 执行构造函数中代码(为这个新对象添加属性);
  4. 返回新的对象。

创造出不同实例的特点:

person1和person2都有一个constructor属性,都指向了Person。

person1.constructor === Person;  //true
person2.constructor === Person;  //true
person1.constructor === person2.constructor;  //true
 

对象的constructor属性最初是用来标识对象类型的,但是用instanceof操作符更可靠。

person1.instanceof Object;  //true
person1.instanceof Person;  //true
person2.instanceof Object;  //true
person2.instanceof Person;  //true
 

构造函数模式优缺点

优点:创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;而这正是构造函数模式胜过工厂模式的地方。

缺点:构造函数里的每个方法都要在实例上重新创造一遍,不可复用。如果像下面的代码那样讲方法抽象出来,那么如果对象需要定义很多方法,那么就要定义很多全局函数,毫无封装性。

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

function sayName() {
    alert(this.name);
}
 

理解构造函数

  1. 构造函数也是函数,不存在函数的特殊用法。
  2. 构造函数和其他函数的区别,在于调用它们的方式不同。

    任何函数,只要通过new操作符来调用,那它就可以作为构造函数;而任何函数,如果不通过new操作符来调用,那它跟普通函数也不会有什么两样。

//当做构造函数用
var person = new Person("Michael282694", 5, "MLer");
person.sayName();  //Michael282694

//当做普通函数用,添加到宿主对象window,this指向Global对象
Person("Michael", 6, "MLer");
window.age;  //6
window.sayName();  //Michael

//在另一个对象的作用域中调用
var o = new Object();
Person.call(o, "Cindy282694", 7, "MLer");
o.sayName();  // Cindy282694
 

3.原型模式

//原型模式一

function Person() {
}

Person.prototype.name = "MirrorAvatar";
Person.prototype.age = 4;
Person.prototype.job = "coder";
Person.prototype.sayName = function() {
    alert(this.name);
}

var person1 = new Person();
person1.sayName();  //MirrorAvatar

var person2 = new Person();
person2.sayName();  //MirrorAvatar
 

代码特点

  1. Person函数为空;
  2. 属性方法都绑定在Person函数的原型(prototype)上。
//原型模式二,减少模式一不必要的输入
function Person() {
}

Person.prototype = {

    name: "MirrorAvatar",
    age: 4,
    job: "coder",
    sayName: function() {
        alert(this.name);
    }
};

Person.prototype.constructor === Person;  //false
Person.prototype.constructor === Object;  //true
person1 instanceof Person;  //true
person2 instanceof Object;  //true
 

特点

  1. Person函数为空;
  2. Person的prototype是以字面量的形式定义的3;
  3. 此时Person函数原型对象的constructor不再指向Person而是Object。
//原型模式三,针对上述3的缺陷
function Person() {
}

Person.prototype = {

    constructor: Person,
    name: "MirrorAvatar",
    age: 3,
    job: "coder",
    sayName: function() {
        alert(this.name);
    }
};

//以上重设了constructor指向,导致constructor的[[Enumerable]]特性设置成true,默认是false的。
//重设构造函数,只适用于ECMAScript 5兼容的浏览器 
Object.defineProperty(Person.prototype, "constructor",{
    enumerable: false,
    value: Person
});
 

重写整个原型对象

重写原型对象切断了现有原型与任何之前已经存在的对象实例之间的联系;它们引用的仍然是最初的原型。

function Person() {
}

var friend = new Person();

Person.prototype = {
    constructor: Person,
    name: "Nicholas",
    age: 29,
    job: "Software Engineer",
    sayName: function() {
        alert(this.name);
    }
};

friend.sayName();  //Error
 

重写原型对象前:

重写原型对象前

重写原型对象后:

重写原型对象后

原型模式缺点:

  1. 它省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值;
  2. 对于引用类型值的属性,体现不出实例的个性。
function Person() {
}

Person.prototype = {
    constructor: Person,
    name: "MirrorAvatar",
    age: 2,
    job: "coder",
    friends: ["Cindy","Cindy282694"],
    sayName: function() {
        alert(this.name);
    }
}

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

person1.friends.push("Michael");

console.log(person1.friends);  //"Cindy,Cindy282694,Michael"
console.log(person2.friends);  //"Cindy,Cindy282694,Michael"

person1.friends === person2.friends;  //true
 

4.组合使用构造函数模式和原型模式

创建自定义类型的最常见方式。既复用方法,又共享共同属性。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["Cindy", "Michael"];
}

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

var person1 = new Person("Cindy282694", 4, "coder");
var person2 = new Person("MirrorAvatar", 3, "coder");

person1.friends.push("Michael282694");
console.log(person1.friends);  //"Cindy,Michael,Michael282694"
console.log(person2.friends);  //"Cindy,Michael"

person1.friends === person2.friends;  //false
person1.sayName === person2.sayName;  //true
 

这种构造函数与原型混成的模式,是目前在ECMAScript中使用最广泛、认同度最高的一种创建自定义类型的方法。可以说,这是用来定义引用类型的一种默认模式。

5.动态原型模式

封装性比较好

function Person(name, age, job) {

    //属性
    this.name = name;
    this.age = age;
    this.job = job;

    //方法
    if(typeof this.sayName != "function") {

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

var friend = new Person("MirrorAvatar", 3, "coder");
friend.sayName();  //MirrorAvatar
 

6.寄生构造函数模式

这个模式其实和第一个模式“工厂模式”一样,不信你看。

通常,在前述的几种模式都不适用的情况下,可以使用寄生(parasitic)构造函数模式。这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象;但从表面上看,这个函数又很像是典型的构造函数。

function Person(name, age, job) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.job = job;
    o.sayName = function() {
        alert(this.name);
    }
    return o;
}

var friend = new Person("MirrorAvatar", 2, "coder");
friend.sayName();
 

特点:

首先,返回的对象与构造函数或者与构造函数的原型属性之间没有关系;也就是说,构造函数返回的对象与在构造函数外部创建的对象没有什么不同。

7.稳妥构造函数模式

所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(这些环境中会禁止使用this和new),或者在防止数据被其他应用程序(如Mashup程序)改动时使用。

稳妥构造函数遵循与寄生构造函数类似的模式,但有两点不同:一是新创建对象的实例方法不引用this;二是不使用new操作符调用构造函数。

function Person(name, age, job) {

    //创建要返回的对象
    var o = new Object();

    //可以在这里定义私有变量和函数

    //添加方法
    o.sayName = function() {
        alert(name);
    }

    //返回对象
    return o;
}

var friend = Person("MirrorAvatar", 3, "coder");
friend.sayName();  //"MirrorAvatar"
 

特点: 1. 没有new操作符 2. 没有this

1
0
分享到:
评论

相关推荐

    Windows 脚本编程核心技术精解

    2. ActiveX是COM的一种扩展,用于创建可跨平台、跨网络的交互式对象,常用于脚本编程中调用系统服务。 四、Windows脚本对象模型(WScript Object Model) 1. WScript对象模型提供了与系统进行交互的接口,如...

    adobe AI CS2脚本编程指南

    - **颜色对象**:用于设置和管理颜色,包括RGB、CMYK等多种颜色模式。 - **文本对象**:用于处理文本,支持设置字体、大小、对齐方式等属性。 - **选择对象**:用于管理和操作当前选中的对象,支持获取选中状态、...

    用JavaScript写的PS图象处理软件脚本。用于图像处理自动化

    在Photoshop中,JavaScript是通过 ExtendScript 工具集来实现的,它是一种基于ECMAScript(JavaScript的标准)的脚本语言,允许开发者控制Photoshop的各个功能。批处理是JavaScript在Photoshop中最常见的应用场景,...

    前端优化合集

    10. **数组和对象的遍历**:使用`Array.forEach`或`Array.every`等ECMAScript 5提供的迭代方法,提高代码可读性。 11. **字符串引号规范**:统一使用单引号 `'`,以方便在创建HTML字符串时避免转义问题。 12. **...

    基于JavaScript和html的高性能模板引擎

    1. JavaScript基础:作为前端的主要开发语言,JavaScript提供了处理DOM(文档对象模型)和数据操作的能力。模板引擎通常会使用JavaScript来解析模板、操作数据并更新视图。ECMAScript是JavaScript的标准化规格,理解...

    百分点(14问).pdf

    Promise对象有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。then方法则是用来处理Promise对象状态变为fulfilled时的回调函数。 快速排序是一种高效的排序算法,它采用了分而治之的策略...

    flex 实现图片另存为

    - **`FileStream` 类**:创建一个文件流对象,用于打开、读取或写入文件。 - **`openAsync()` 方法**:异步打开文件,参数包括 `File` 对象和 `FileMode` 枚举值。此处使用 `FileMode.WRITE` 表示以写入模式打开...

    es6-activerecord

    - **类(Class)**:模拟面向对象编程的类结构,简化对象创建。 - **箭头函数(Arrow Functions)**:简洁的函数定义方式,处理this上下文。 - **模板字符串(Template literals)**:用于构建字符串,支持变量...

    Learn.javascript

    每个JavaScript对象都有一个proto属性,指向创建它的构造函数的原型对象。通过这种方式,对象可以共享其原型的方法和属性,实现代码复用。 ES6(ECMAScript 2015)引入了许多新特性,如箭头函数、模板字符串、let和...

    photoshopJavaScriptSample:一些 PhotoShop JavaScript 代码

    JavaScript在Photoshop中的工作原理是基于 ExtendScript,这是Adobe开发的一种基于ECMAScript(JavaScript的标准)的脚本语言。它允许开发者访问Photoshop的完整对象模型,包括文档、图层、选择区、颜色模式等,从而...

    PhotoshopWith[removed]具有Javascript源代码的Photoshop

    ExtendScript是一种基于ECMAScript(JavaScript的基础)的脚本语言,专门设计用来控制Adobe的应用程序,包括Photoshop。通过这种技术,开发者可以创建复杂的脚本来调整图像参数、执行批量操作、创建自定义面板、甚至...

    架构脑图.pdf

    - **Java语言概述**:Java是一种广泛使用的面向对象编程语言,以其跨平台性(Write Once, Run Anywhere, WORA)著称。 - **对象**:Java中的一切都是基于对象的,通过类来定义对象,并使用对象进行编程。 - **XML & ...

    illustrator-scripts-collection:Illustrator 脚本集合,包含在子模块中

    - **批量处理**: 脚本可以用来批量修改多个文件,例如统一调整画板大小、更改色彩模式或导出格式。 - **自定义工作流**: 根据个人或团队的工作需求,创建定制化工具,如自动布局、形状生成、图案制作等。 - **...

Global site tag (gtag.js) - Google Analytics