JS创建对象的几种方式
一.直接创建(不推荐)
字面量:
var o1 = { name:'xiaoming', age:20, sayHi:function(){ console.log("Hi"); } } console.log(o1) console.log(o1 instanceof Object) //true
new操作符:
var o2 = new Object(); o2.name = 'xiaoming'; o2.age = 20, o2.sayHi = function(){ console.log("Hi"); } console.log(o2) console.log(o2 instanceof Object) //true
这种创建方式的缺点显而易见,每创建一个对象,都需要设置每一个属性,造成大量代码重复。
二.工厂模式
function cStudent(name,age) { var o = new Object(); o.name = name; o.age = age; o.sayHi = function () { console.log("Hi"); } return o; } var o3 = cStudent('xiaoming',20); var o4 = cStudent('xiaomei',18); console.log(o3 instanceof Object) // true
工厂模式解决了上述代码重复的问题,但是不知道当前对象是什么类型,因为全部都是Object。
三.构造函数
function Student(name,age) { //为了区别普通函数,构造函数名开头大写 this.name = name; this.age = age; this.sayHi = function () { console.log("Hi"); } } var o5 = new Student('xiaoming',20); var o6 = new Student('xiaomei',20); console.log(o5.__proto__ == o6.__proto__) //true console.log(o5.age == o6.age) //true console.log(o5.sayHi == o6.sayHi) //false
可以看到,o5和o6的原型对象是相同的,属性age也是相同的,但是sayHi的方法是不同的。也就是说构造函数的实例对象可以继承属性,但是不能继承方法。
四.原型模式
function Person() {} Person.prototype.name = 'xiaoming'; Person.prototype.age = 20; Person.prototype.sayHi = function () { console.log('hi') } var o7 = new Person(); var o8 = new Person(); console.log(o7.sayHi == o8.sayHi) //true
这里将sayHi方法添加到了Person的原型对象上,所以o7和o8访问的都是同一组属性和同一个sayHi()函数。由此衍生出混合模式
五.混合模式(推荐)
function Student(name,age) { this.name = name; this.age = age; } Student.prototype = { constructor:Student, sayHi : function () { console.log('Hi') } } var o9 = new Student('xiaoming',20); var o10 = new Student('xiaomei',20); console.log(o9.age == o10.age) //true console.log(o9.sayHi == o10.sayHi) //true
可以看出,混合模式共享着对相同方法的引用,又保证了每个实例有自己的私有属性。最大限度的节省了内存。
六.动态原型模式
function Student(name,age) { this.name = name; this.age = age; if(typeof this.sayHi != "function"){ Student.prototype.sayHi = function () { console.log('Hi') } } } var o11 = new Student('xiaoming',20); var o12 = new Student('xiaomei',18); console.log(o11.sayHi == o12.sayHi) //true
这里只在sayHi()方法不存在的情况下,才会将它添加到原型中。
七.Object.create
// new Object() 方式创建 var a = { rep : 'apple' } var b = new Object(a) console.log(b) // {rep: "apple"} console.log(b.__proto__) // {} console.log(b.rep) // {rep: "apple"} // Object.create() 方式创建 var a = { rep: 'apple' } var b = Object.create(a) console.log(b) // {} console.log(b.__proto__) // {rep: "apple"} console.log(b.rep) // {rep: "apple"}
new Object() 通过构造函数来创建对象, 添加的属性是在自身实例下。
Object.create() es6创建对象的另一种方式,可以理解为继承一个对象, 添加的属性是在原型下。