js之创建对象2
方法三:原型模式
1.试想一下,能不能把sayName拿出来放在一个公共区域里,这样举例子可能有些不合适,因为并不是说你用sayName的时候我就不可以用,我们想要的是不管谁去取,多少对象同时使用都可以,但是sayName只有一个。这样的想法就诞生原型模式,这个公共区域就是prototype。
如图所示,无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数。

创建一个prototype属性,该属性指向函数的原型对象。而原型对象会获取一个constructor属性,该属性指向对应的构造函数。而对象的实例中则含有一个[[prototype]]的属性,它指向原型对象。这个属性对脚本是完全不可见的,但是可以通过isPrototypeOf()方法来确定对象之间是否存在这种关系,如果说[[prototype]]指向调用isPrototype()方法的对象(obj.prototype),这个方法就返回true:
alert(Person.prototype.isPrototypeOf(person1));//true
ECMAscript 5中新增加一个方法Object.getPrototypeOf(),返回[[Prototype]]的值:
alert(Object.getPrototypeOf(person1) == Person.prototype);//true alert(Object.getPrototypeOf(person1).name);//Nicole
原型创建代码:
function Person(){ } Person.prototype.name = "Nicole"; Person.prototype.age = 12; Person.prototype.job = "software engnieer"; Person.prototype.sayName = function(){ alert(this.name); } var person1 = new Person(); person1.sayName();//Nicole var person2 = new Person(); person2.sayName();//Nicole alert(person1.sayName == person2.sayName);//true
2.更简单的原型语法:
前面例子每添加一个属性和方法就要敲一遍Person.prototype,很麻烦,可以使用字面量重写整个原型对象:
function Person(){ } Person.prototype = { name:"Nicole", age:12, job:"software engnieer", sayName:function(){ alert(this.name); } }
在这个例子中,我们将Person.prototype设置等于一个以字面量形式创建的新对象,最终结果相同,但是要注意的是,constructor不再指向Person,指向Object。
alert(Person.prototype.constructor == Person);//false
因此需要人工的配置constructor的指向:
Person.prototype = { constructor:Person, name:"Nicole", age:12, job:"software engnieer", sayName:function(){ alert(this.name); } }
这样写依然有一个问题,就是重写prototype切断了,现有原型和重写前已经存在的实例的联系,它们引用的依然是最初的原型:
function Person(){ } var person1 = new Person(); Person.prototype = function(){ constructor:Person, name:"Nicole" }; alert(person1.name);//error
原型对象的缺点:
共享是把双刃剑,它就带来了便利,也带来了麻烦,比方说:
function Person(){ }; Person.prototype = { constructor:Person, name:"Nicole", age:12, job:"software engnieer", friends:['hah','hhe'], sayName:function(){ alert(this.name); } }; var person1 = new Person(); var person2 = new Person(); person1.friends.push('black'); alert(person2.friends);//'hah','hhe','black'
修改一个实例的原型方法或者属性,所有相关实例都会相应的变化。
方法四:组合使用构造函数模式和原型模式
为了解决原型模式的缺点,我们可以使用构造函数定义实例属性,用原型模式定义方法和共享的属性。
function Person(name,age,job){ this.name = name; this.age = age; this.job = job; this.friends=["hello","world"]; } Person.prototype = { constructor:Person; sayName:function(){ alert(this.name); } } var person1 = new Person("Nicole",12,"software engnieer"); var person2 = new Person("blue",14,"writer"); person1.friends.push("!"); alert(person1.friends);//"hello","world","!" alert(person2.friends);//"hello","world"

浙公网安备 33010602011771号