1:对象字面量
var foo = {
age:10
};
2:通过Object构造函数
var foo = new Object()
foo.age = 10;
3:通过Object.create创建
let foo = {
age:10
};
let f = Object.create(foo);
console.log(f.age);//10
以上创建对象的缺点:
这三种方式,当需要创建多个对象时,会产生大量重复代码
4:通过工厂模式
function createPerson(age) {
let obj = new Object();
obj.age = age;
return obj;
}
let person = createPerson(10);
通过工厂的方式可以节省大量重复代码,但无法识别对象的类型, 即通过instanceof无法判断具体属于哪个实例,因为通过工厂模式创建的对象都属于Object的实例
5:构造函数模式
function foo() {
this.age = 10;
this.run = function () {
console.log(this.age)
}
}
let f = new foo();
console.log(f instanceof foo); //true
console.log(f instanceof Object); //true
通过构造函数创建的对象,可以识别出具体从哪里构造出来的,但构造函数内的方法会被重复创建,造成内存空间的浪费
原型模式
function Foo() {
}
Foo.prototype.age = 10;
Foo.prototype.run = function () {
console.log(this.age)
};
let f = new Foo();
f.run(); //10
通过原型模式创建的对象,可以让所有的实例对象共享原型的属性和方法,并且因为原型上属性是共享的,所有很不方便维护
构造函数和原型组合模式
function Foo(age) {
this.age = age;
}
Foo.prototype= {
//原型对象都有constructor属性(指针):它指向该原型对象的构造函数
constructor:Foo,
PI:3.14,
run:function () {
console.log(this.age)
}
};
let f = new Foo(10);
f.run(); //10
console.log(Foo.prototype.constructor == Foo); //true
推荐使用,通过构造函数定义每个实例对象的私有属性,通过原型定义公有方法和属性,不仅节省了内存,也可以向构造函数传递参数
为什么要在原型上添加constructor:Foo?
因为原型对象的constructor默认是指向原型对象的构造函数,所以当我重写了Foo的prototype原型对象时, Foo.prototype原型对象上是没有constructor属性,会继续往父级原型链上查找,最终会是ƒ Object() { [native code] } 而按照约定,需要让constructor指向原型对象的构造函数,所以需要添加 constructor:Foo,如果不添加则 console.log(Foo.prototype.constructor == Foo); 结果为false,但也并不影响使用。