JavaScript 对象的创建

Object类型是JavaScript中使用最多的一种类型。创建Object实例的方式有多种,接下来一一列举。

1. Object构造函数

var person = new Object();
person.name = "Brittany";
person.age = 23;
person.job = "web front-end engineer";
person.sayName = function() {
    console.log(this.name);
};
person.sayName();   //Brittany

2. 对象字面量模式

var person = {
    name: "Brittany",
    age: 23,
    job: "web front-end engineer",
    sayName: function() {
        console.log(this.name);
    }
};
person.sayName();

      虽然Object构造函数或对象字面量都可以用来创建单个对象,但这些方式有个明显的缺点:使用同一个接口创建很多对象,会产生大量的重复代码。为解决这个问题,可以使用工厂模式的一种变体。

3. 工厂模式 

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

var person1 = createPerson("Brittany", 23, "Software Engineer");
var person2 = createPerson("Sam", 26, "Software Engineer");
console.log(typeof person1);   //Object

      工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型)。如代码中只能检测出person1为Object类型。随着JavaScript的发展,又一个新模式出现了。

4. 构造函数模式

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("Brittany", 23, "Web front-end engineer");
var person2 = new Person("Closure", 26, "Manager");
person1.sayName();
person2.sayName();
console.log(person1.sayName == person2.sayName);   //false

      使用构造函数的主要问题:每个方法都要在每个实例上重新创建一遍。如代码中所示,person1的sayName和person2的sayName不相等。可以将函数定义转移到构造函数外部来解决。

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

      sayName函数的定义转移到了构造函数外部。而在构造函数内部,我们将sayName属性设置成等于全局的sayName函数。这样一来,由于sayName包含的是一个指向函数的指针,因此person1和person2对象就共享了在全局作用域中定义的同一个sayName()函数。这的确解决了两个函数做同一件事的问题,可是新问题又来了:在全局作用域中定义的函数实际上只能被某个对象调用,这让全局作用域有点名不副实。而更让让人无法接受的是:如果需要定义很多方法,那就要定义很多个全局函数,于是这个自定义的引用类型就无封装性可言。这些问题可通过使用原型模式来解决。

5. 原型模式

function Person() {}
Person.prototype.name = "Brittany";
Person.prototype.age = 23;
Person.prototype.job = "Web front-end engineer";
Person.prototype.getName = function() {
    console.log(this.name);
};
var p1 = new Person();
var p2 = new Person();

console.log(p1.name);                    //Brittany
console.log(p2.name);                    //Brittany
console.log(p1.getName == p2.getName);   //true

      实例中创建的属性会覆盖原型中的同名属性,不能修改原型中的属性。

p1.name = "Susan";
console.log(p1.name);                    //Susan

     hasOwnProperty()检测一个属性是否存在于实例中。

console.log(p2.hasOwnProperty("name"));  //false
p2.name = "koko";
console.log(p2.hasOwnProperty("name"));  //true
delete p2.name;
console.log(p2.hasOwnProperty("name"));  //false

     isPropertyOf()

console.log(Person.prototype.isPrototypeOf(p1));   //true
console.log(Person.prototype.isPrototypeOf(p2));   //true

     getPropertyOf()

console.log(Object.getPrototypeOf(p1) == Person.prototype);  //true
console.log(Object.getPrototypeOf(p1));                      //Person

     

 

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。