头部背景图片
小畅的学习笔记 |
小畅的学习笔记 |

js创建对象

1. 对象字面量方式

var person = {
name: "XiaoMing",
age: 29,
job: "Software Engineer",
sayName: function () {
    alert(this.name)
}

2.object构造函数

var person = new Object();
person.name = "XiaoMing";
person.age = 18;
person.job = "software Engineer";

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

使用object构造函数和对象字面量方式创建对象有一个缺点:如果我们想创建与该对象同类型的对象,就会产生大量重复的代码。

3.工厂模式(用函数来封装以特定接口创建对象的细节)

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('jill',18,'software');
var person2 = createPerson('vane',23,'student');

使用这种方式创建对象虽然解决了创建多个结构相似的对象的问题,但是没有解决对象识别的问题(即无法判断一个对象的类型)

4.构造函数模式

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

var person1 = new Person('xiaoming',18,'software');
var person2 = new Person('xiaohong',20,'student');

alert(person1.constructor == Person) //true
alert(person1 instanceof Object);//true
alert(person1 instanceof Person);//true

创建自定义构造函数可以将它的实例标识为一种特定的类型,但是其中的每个方法都要在每个实例上重新创建一遍。即会导致不同的作用域链和标识符解析,但是创建Function新实例的机制是相同的。所以
person1.sayName == person2.sayName //false

5. 原型模式

function Person() {}
// constructor -> Person
Person.prototype.name = "xiaoming";
Person.prototype.age = 18;
Person.prototype.job = "software";
Person.prototype.sayName = function () {
    alert(this.name);
}

// constructor -> object
// Person.prototype = {
//     constructor: Person,
//     name: "xiaoming",
//     age: 18,
//     job: "software",
//     sayName: function () {
//         alert(this.name);
//     }
// }

var person5 = new Person();
person5.sayName(); // xiaoming
var person6 = new Person();
person6.sayName(); //xiaoming
alert(person5.sayName === person6.sayName);//true

关于原型模式,每个函数在创建时,都有一个prototype属性,指向该函数的原型对象。使用原型对象的好处是可以让所有对向实例共享它所包含的属性和方法。通过 hasOwnPrototype()方法可以判断属性是实例属性还是原型属性。若为实例属性,返回true,否则返回false。
实例中的指针([[ Prototype ]])指向原型。
原型对象的问题:原型中的所有属性是被很多实例共享的,这种共享对于函数非常合适,然而对于包含引用类型值的属性来说,问题就比较突出。

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

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

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["vane", "ming"];
}
Person.prototype = {
    constructor: Person,
    sayName: function () {
        alert(this.name);
    }
}

var person9 = new Person("xiaoming", 12, "student");
var person10 = new Person("xiaohong", 32, "doctor");

person9.friends.push('xiaogang');

alert(person9.friends);//vane,ming,xiaogang
alert(person10.friends);//vane,ming
alert(person9.friends === person10.friends);//false
alert(person9.sayName === person10.sayName);//true

7.动态原型模式

大多数开发人员看到独立的构造函数和原型时,会感到困惑。我们使用动态原型模式解决这一问题。即通过检查某个应该存在的方法是否有效,来决定是否需要初始化原型。

function Person(name, age, job) {
    this.name = name;
    this.age = age;
    this.job = job;
    this.friends = ["vane", "ming"];

    //    方法
    if (typeof this.sayName != "function") {
        //使用动态原型模式时,不能使用对象字面量重写原型。如果在已经创建了实例的情况下重写原型,那么就会切断现有实例与新原型之间的联系
        Person.prototype.sayName = function () {
            alert(this.name);
        }
    }
}

8.寄生构造函数模式

基本思想:创建一个函数,其作用是封装创建对象的代码,然后返回新创建的对象。

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 person = new Person("ming",18,"software");
person.sayName();//ming

构造函数返回的对象与在构造函数外部创建的对象没什么不同,不能使用instanceof来确定对象的类型。

9.稳妥构造函数模式

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

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

    o.sayName = function () {
        alert(name);
    }
    return o;
}
var person12 = Person("ming",29,"student");
person12.sayName();//ming
Lililich's Blog