创建对象

113 阅读2分钟

这是我参与11月更文挑战的第18天,活动详情查看:2021最后一次更文挑战

工厂模式

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('nickname1', 10, 'student');
var person2= createPerson('nickname2', 25, 'teacher');

工厂模式解决了创建多个相似对象的问题。

构造函数模式

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

var person1= createPerson('nickname1', 10, 'student');
var person2= createPerson('nickname2', 25, 'teacher');

构造函数和工厂模式不同之处在于:

  • 没有显示地创建对象;
  • 直接将属性和方法赋给了 this 对象;
  • 没有 return 语句;
检测对象类型

使用 instanceof 操作符更可靠。

console.log(person1 instanceof Object); // true
console.log(person1 instanceof Person); // true
构造函数的问题

使用构造函数需要每个方法都要在每个实例上重新创建一遍。

原型模式

每个函数都有一个 prototype 属性。这个属性是一个指针,指向一个对象,这个对象的用途是由特定类型的所有实例共享的属性和方法。可以让所有对象实例共享它所包含的属性和方法。

function Person() {}

Person.prototype.name = "nickname";
Person.prototype.age = 20;
Person.prototype.job = "teacher";
Person.prototype.sayName = function() {
    console.log(this.name);
};

var person1 = new Person();
person1.sayName(); // "nickname"

var person2 = new Person();
person2.sayName(); // "nickname"

console.log(person1.sayName == person2.sayName); // true

只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype 属性,这个属性指向函数的原型对象。所有原型对象都会自动获得一个 constructor 属性。

更简单的原型语法

上面的例子中每添加一个属性和方法就要重写一遍 Person.prototype。有一种更常见的做法是用一个包含所有属性和方法的对象来重写整个原型对象:

function Person() {}

Person.prototype = {
    name: "nickname",
    age: 20,
    job: "teacher",
    sayName: function() {
        console.log(this.name);
    }
};

寄生构造函数模式

这种模式的基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,再返回创建的对象。

function Person(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 friend = new Proson("nickname", 20, "teacher");
friend.sayName();