资讯专栏INFORMATION COLUMN

javascript创建对象

Keven / 378人阅读

摘要:就是通过调用构造函数而创建的那个对象实例的原型对象。与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也没有什么关系,因此操作符对这种对象也没有什么意义

虽然Object构造函数或对象字面量都可以用来创建单个对象,但是这些方法有明显的缺点:使用同一个接口创建很多对象,会产生大量重复代码。因此人们开始使用工厂模式。

工厂模式

这种模式抽象了创建具体对象的过程

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

var person1 = new createPerson("liaojin",18);
var person2 = new createPerson("xiaoguan",20);

函数createPerson()能够根据接受的参数来构建一个包含所有必要信息的Person对象。可以无数次的调用这个函数,而每次它都会返回一个包含两个属性以个方法的对象。工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。

构造函数模式

使用构造函数将上述例子重写

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

var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);

在这个例子中,Person()函数取代了createPerson()函数。注意到Person()中的代码与createPerson()的不同之处:
1.没有显示的创建对象
2.直接将属性和方法赋值给了this对象
3.没有return语句
要创建Person新实例,必须使用new操作符。这种方式会经理以下四个步骤:
1.创建一个新对象
2.将构造函数的作用域赋给新对象(因此this就指向了这个新对象)
3.执行构造函数中的代码(为这个新对象添加属性)
4.返回新对象
person1和person2分别保存着Person的一个不同实例。这两个对象都有一个constructor属性,该属性指向Person。

alert(person1.constructor == Person);//true
alert(person2.constructor == Person);//true

对象的constructor属性最初是用来表示对象类型的,但是检测对象类型还是instanceof更可靠一些。这个例子中创建的所有对象即是Object的实例,同时也是Person的实例。
创建自定义的构造函数意味着将来可以将它的实例标识为一种特定的类型;person1和person2之所以同时是Object的实例,是因为所有对象均继承自Object.

将构造函数当做函数

构造函数与其他函数唯一的区别就在于调用他们的方式不同。
任何函数只要通过new操作符来调用,那他就可以作为构造函数;而任何函数如果不通过new操作符来调用,那他跟普通函数没有区别。
如上述例子中的Person()函数可以通过下列任何一种方式来调用。

//当做构造函数调用
var person = new Person("liaojin",18);
person.sayName();//liaojin

//作为普通函数调用
Person("lihua",12);
window.sayName();//lihua

//在另一个对象的作用域调用
var o = new Object();
Person.call(o,"xiaoguan",20);
o.sayName();//xiaoguan
构造函数的问题

构造函数模式虽然好用,但是也有缺点。使用构造函数的主要问题,就是每个方法都要在每个实例上重新创建一遍。如同this.sayName =new function(){alert(this.name);};在上面的构造函数中sayName()的方法,person1和person2虽然都调用了这个方法,但是调用的并不是同一个Function实例。因此不同实例的同名函数是不相等的

alert(person1.sayName == person2.sayName);//false

然而创建两个完成同样任务的Function实例的确没有必要;因此可以通过吧函数定义转移到构造函数外部来解决这个问题

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = sayName;
}
function sayName(){
    alert(this.name);
}
var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);

在构造函数内部,我们将sayName属性设置为指向全局的sayName函数,由于sayName包含的是指向函数的指针,person1,person2共享了一个sayName函数,解决了两个函数做同样一件事的问题。
可是随即有产生了新的问题:在全局作用域定义的函数实际上只能被某个对象调用,这让全局函数优点名不副实。如果对象需要定义很多方法,那么就需要定义多个全局函数,于是自定义的引用类型就没有封装性可言了,因此产生了原型模式。

原型模式

我们所创建的每个函数都有一个prototype属性,这个属性是一个指针,指向一个对象,而这个对象的用途就是包含可以由特定类型的所有实例共享的属性和方法prototype就是通过调用构造函数而创建的那个对象实例的原型对象。可以让所有对象的实例共享它所包含的属性和方法。

function Person(){}
Person.prototype.name = "liaojin";
Person.prototype.age = 18;
Person.prototype.sayName = function(){
    alert(this.name);
};

var person1 = new Person();
Person1.sayName();//liaojin
var person2 = new Person();
Person2.sayName();//liaojin

alert(person1.sayName == person2.sayName);//true
组合使用构造函数模式和原型模式

构造函数用于定义实例属性,而原型模式用于定义方法和共享的属性。这样每个实例都会有自己的实例属性的副本,但同时又共享着对方法的引用,最大限度地节省了内存。

function Person(name,age){
    this.name = name;
    this.age = age;
    this.friends = ["lucy","lily"];
}

Person.prototype = {
    constructor:Person,
    sayName:function(){
        alert(this.name);
    }
}
var person1 = new Person("liaojin",18);
var person2 = new Person("xiaoguan",20);

person1.friends.push("lihua");
alert(person1.friends);//lucy,lily,lihua
alert(person2.friends);//lucy,lily
alert(person1.friends == person2.friends);//false
alert(person1.sayName == person2.sayName);//true
动态原型模式

有其他面向对象经验开发的人员看到独立的构造函数和原型时,很可能会肥肠困惑,动态原型模式就是解决这个问题的一个方案。

function Person(name,age){
    this.name = name;
    this.age = age;
}
if(typeof this.sayName != "function"){
    Person.prototype.sayName = function(){
        alert(this.name);
    };
}

这里只在sayName()方法不存在的情况下才会将它添加到原型中。这段代码只会在初期调用才会执行。

寄生构造函数模式

这个模式可以在特殊的情况下用来为对象创建构造函数。假设我们想创建一个具有额外方法的特殊数组。由于不能直接修改Array构造函数,因此可以使用这个模式。

function SpecialArray(){
    var values = new Array();
    values.push.apply(values,arguments);
    values.toPipedString = function(){
        return this.join("|");
    };
    return values;
}
var colors = new SpecialArray["red","blue","green"];
alert(colors.toPipedString());//red|blue|green

说明:关于寄生构造函数模式,首先返回的对象与构造函数或者与构造函数的原型属性之间没有关系;构造函数返回的对象与在构造函数外部创建的对象没有什么不同。因此不能依赖instanceof操作符来确定对象的类型。

稳妥构造函数模式

所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。稳妥对象最适合在一些安全的环境中(禁止使用this和new的环境),或者在防止数据被其他应用程序改动时使用。与寄生构造函数类似的模式;但有两点不同:1.新创建对象的实例方法不引用this;2.不使用new操作符调用构造函数;

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

//使用
var friend = Person("liaojin",18);
friend.sayName();//liaojin

这样变量person中保存的是一个稳妥对象,而除了调用sayName()方法外,没有别的方法可以访问其数据成员,即使有其他代码会给这个对象添加方法或数据成员,但也不可能有别的办法访问传入到构造函数中的原始数据,非常适合在某些安全执行环境下使用。
与寄生构造函数模式类似,使用稳妥构造函数模式创建的对象与构造函数之间也没有什么关系,因此instanceof操作符对这种对象也没有什么意义

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/95645.html

相关文章

  • JavaScript中的面向对象(object-oriented)编程

    摘要:对象在中,除了数字字符串布尔值这几个简单类型外,其他的都是对象。那么在函数对象中,这两个属性的有什么区别呢表示该函数对象的原型表示使用来执行该函数时这种函数一般成为构造函数,后面会讲解,新创建的对象的原型。这时的函数通常称为构造函数。。 本文原发于我的个人博客,经多次修改后发到sf上。本文仍在不断修改中,最新版请访问个人博客。 最近工作一直在用nodejs做开发,有了nodejs,...

    JerryZou 评论0 收藏0
  • [译] V8 使用者文档

    摘要:注意句柄栈并不是调用栈中的一部分,但句柄域却在栈中。一个依赖于构造函数和析构函数来管理下层对象的生命周期。对象模板用来配置将这个函数作为构造函数而创建的对象。 如果你已经阅读过了上手指南,那么你已经知道了如何作为一个单独的虚拟机使用 V8 ,并且熟悉了一些 V8 中的关键概念,如句柄,域 和上下文。在本文档中,还将继续深入讨论这些概念并且介绍其他一些在你的 C++ 应用中使用 V8 的...

    lei___ 评论0 收藏0
  • JavaScript对象

    摘要:对象的分类内置对象原生对象就是语言预定义的对象,在标准定义,有解释器引擎提供具体实现宿主对象指的是运行环境提供的对象。不过类型是中所有类型的父级所有类型的对象都可以使用的属性和方法,可以通过的构造函数来创建自定义对象。 对象 javaScript中的对象,和其它编程语言中的对象一样,可以比照现实生活中的对象来理解。在JavaScript中,一个对象可以是一个单独拥有属性和类型的实体。和...

    xavier 评论0 收藏0
  • JavaScript基础之创建对象、原型、原型对象、原型链

    摘要:在最开始的时候,原型对象的设计主要是为了获取对象的构造函数。同理数组通过调用函数通过调用原型链中描述了原型链的概念,并将原型链作为实现继承的主要方法。 对象的创建 在JavaScript中创建一个对象有三种方式。可以通过对象直接量、关键字new和Object.create()函数来创建对象。 1. 对象直接量 创建对象最直接的方式就是在JavaScript代码中使用对象直接量。在ES5...

    wangbjun 评论0 收藏0
  • JavaScript 工厂函数 vs 构造函数

    摘要:当谈到语言与其他编程语言相比时,你可能会听到一些令人困惑东西,其中之一是工厂函数和构造函数。好的,让我们用构造函数做同样的实验。当我们使用工厂函数创建对象时,它的指向,而当从构造函数创建对象时,它指向它的构造函数原型对象。 showImg(https://segmentfault.com/img/bVbr58T?w=1600&h=900); 当谈到JavaScript语言与其他编程语言...

    RayKr 评论0 收藏0
  • JavaScript学习笔记(二) 对象与函数

    摘要:在中函数是一等对象,它们不被声明为任何东西的一部分,而所引用的对象称为函数上下文并不是由声明函数的方式决定的,而是由调用函数的方式决定的。更为准确的表述应该为当对象充当函数的调用函数上下文时,函数就充当了对象的方法。 引言:当理解了对象和函数的基本概念,你可能会发现,在JavaScript中有很多原以为理所当然(或盲目接受)的事情开始变得更有意义了。 1.JavaScript...

    jeffrey_up 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<