创建对象使用new Object()或者对象字面量都可以创建对象,但是这样创建的对象过于简单,不易于对象的属性与方法的扩展与继承。 下面讲的对象可以与JavaEE中的bean做类比。工厂模式对,首先可能想到的是使用设计模式中的工厂模式function createPizza(type) { var o = new Object(); o.type = type; o.bake = function() { alert(‘Start~’); alert(this.type); alert(‘End~’); }; return o;}var cheesePizza = createPizza(‘cheese’);var veggiePizza = createPizza(‘veggie’);cheesePizza.bake();优点工厂模式解决了创建多个类似对象的问题缺点对象无法识别,即创建出来的对象无法通过instanceof等分析出属于哪种类型构造函数模式用构造函数可用来创建特定类型的对象// 构造函数首字母遵循OO语言惯例进行大写function Pizza(type) { this.type = type; this.bake = function() { alert(‘Start~’); alert(this.type); alert(‘End~’); };}var cheesePizza = new Pizza(‘cheese’);var veggiePizza = new Pizza(‘veggie’);cheesePizza.bake();与工厂模式相比:没有在方法中显示创造对象(o);直接将属性与方法赋值给this;没有return语句在用new的时候,会经历一下4步:创建一个新对象将构造函数的作用域赋值给新对象(此时this指向新对象)执行构造函数代码(为对象添加属性)返回新对象如果不使用new,将构造函数当做函数使用,则this指向Global对象(在浏览器中为window对象),当然,可以使用call方法来指定作用域,例如var o = new Object();Pizza.call(o, ‘salty’);o.bake();使用构造函数方法,每个实例对象都有一个constructor构造函数属性,该属性指向Pizza(使用对象字面量、工厂模式方法创建的对象该属性指向Object)cheesePizza.constructor == Pizza检查某个对象属于哪种类型,一般使用instanceof,cheesePizza同时属于Pizza与Object(之所以属于Object,是因为所有对象均继承于Object)cheesePizza instanceof Pizza;cheesePizza instanceof Object;优点与工厂模式相比,构造函数模式能够识别出对象类型与下面的原型模式相比,能够实现对象属性的互相独立,在引用类型属性上很有用缺点每个实例对象的方法都是独立的,导致方法不能够共享原型模式每个函数(不是实例对象)都有一个prototype属性,该属性是一个指针,指向一个对象,对象的用途是包含所有实例共享的属性和方法。prototype通过调用构造函数创建的那个对象实例的原型对象。使用原型对象的好处是可以让所有实例对象共享属性与方法。function Pizza() {}Pizza.prototype.type = ‘original’Pizza.prototype.bake = function() { alert(‘Start~’); alert(this.type); alert(‘End~’);};var cheesePizza = new Pizza();cheesePizza.type = ‘cheese’;var veggiePizza = new Pizza();veggiePizza.type = ‘veggie’;cheesePizza.bake();veggiePizza.bake();各个对象共享属性与方法,同时每个对象都可以建立自己的属性,并屏蔽掉原型对象的同名属性,因为共享属性与方法,所以以下等式成立cheesePizza.bake == veggiePizza.bake对象字面量重写原型对象也可以通过对象字面量来重写整个原型对象:Pizza.prototype = { type: ‘original’, bake: function() { alert(‘Start~’); alert(this.type); alert(‘End~’); }}这样完全重写,原型对象上的constructor属性不再指向Pizza函数(全新的constructor指向Object),不过不影响通过instanceof来识别对象类型。如果constructor特别重要的话,可以显式将它置为适当的值:Pizza.prototype = { constructor: Pizza, type: ‘original’, bake: function() { alert(‘Start~’); alert(this.type); alert(‘End~’); }}不过这种方式会将constructor的属性特征变为可枚举,而默认情况下它是不可枚举的,如果想不可枚举,可以使用Object.defineProperty()方法。原型的动态性对原型对象的修改会体现在实例对象上,即使实例对象先被创建。但是通过对象字面量重写的原型对象则没有该动态性优点定义在原型对象上的属性,能够保证在各实例对象上的共享缺点对于引用类型的属性,各实例的共享会导致额外的问题。组合使用构造函数模式与原型模式整合构造函数模式与原型模式,构造函数模式用于定义实例属性,原型模式用于定义方法和共享属性。动态原型模式寄生构造函数模式稳妥构造函数模式各创建模式在Chrome浏览器中的表现可以通过Chrome浏览器观察使用工厂模式创建的cheesePizza对象属性为:cheesePizza{type: “cheese”, bake: ƒ} bake: ƒ () type: “cheese” proto: constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() defineGetter: ƒ defineGetter() defineSetter: ƒ defineSetter() lookupGetter: ƒ lookupGetter() lookupSetter: ƒ lookupSetter() get proto: ƒ proto() set proto: ƒ proto()使用构造函数模式创建cheesePizza对象属性为:cheesePizzaPizza {type: “cheese”, bake: ƒ} bake: ƒ () type: “cheese” proto: constructor: ƒ Pizza(type) proto: constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() defineGetter: ƒ defineGetter() defineSetter: ƒ defineSetter() lookupGetter: ƒ lookupGetter() lookupSetter: ƒ lookupSetter() get proto: ƒ proto() set proto: ƒ proto()使用原型模式创建cheesePizza对象属性为:cheesePizzaPizza {type: “cheese”} type: “cheese” proto: bake: ƒ () type: “original” constructor: ƒ Pizza() proto: constructor: ƒ Object() hasOwnProperty: ƒ hasOwnProperty() isPrototypeOf: ƒ isPrototypeOf() propertyIsEnumerable: ƒ propertyIsEnumerable() toLocaleString: ƒ toLocaleString() toString: ƒ toString() valueOf: ƒ valueOf() defineGetter: ƒ defineGetter() defineSetter: ƒ defineSetter() lookupGetter: ƒ lookupGetter() lookupSetter: ƒ lookupSetter() get proto: ƒ proto() set proto: ƒ proto()参考文章ESLint 需要约束 for-in (guard-for-in) 个人不定期更新主页