1.原型属性
在js中,函数本身也是一个包含了方法和属性的对象。
prototype
首先先定义一个函数:
function foo(a, b){
return a * b;
}
>foo(2, 3);
在函数定义时被创建的属性中就有prototype属性,其初始值是一个空对象。
2.利用原型添加方法和属性
先构造一个具体的构造器函数Gadget()
function Gadget(name, color){
this.name = name;
this.color = color;
this.whatAreYou = function(){
return "i am" + this.color + this.name;
};
}
这是使用构造器函数,可以通过传参添加属性和方法。
同时,也可以使用构造器函数的prototype属性来增加构造器提供的功能。
为上面的构造器增加两个属性(price和rating)和一个方法(getInfo)。
Gadget.prototype.price = 100;
Gadget.prototype.rating = 3;
Gadget.prototype.getInfo = function(){return this.rating + this.price};
3.使用原型的方法和属性
在向prototype属性中添加完所有的方法和属性后就可以直接用构造器来新建对象了。
var newtoy = new Gadget("zhangsan","white");
>newtoy.name;
>newtoy.whatAreYou();
>newtoy.getInfo();
4.自身属性与原型属性
使用Gadget.prototype来完成对象的访问:
Gadget.prototype.getInfo = function(){
return Gadget.prototype.rating + Gadget.prototype.prince;
};
那么使用this关键字和使用prototype属性有什么不同吗?
首先先回顾一下之前的newtoy对象上:
var newtoy = new Gadget("zhangsan", "white");
>newtoy.name;
>newtoy.rating;
当访问newtoy对象的某个属性,例如newtoy.name,js引擎会遍历该对象的所有属性,从中找出符合要求的,将属性值返回。
此时,如果访问rating属性,js引擎依旧会去对象中遍历属性名,此时,找不到名为rating的属性。接下来,js引擎就会去查询用于创建当前对象的构造器函数的原型,如果在原型中找到了该属性,就立即使用该属性。
此时,牵扯一个概念:原型的实时性(live)
在js中,几乎所有的对象都是通过引用的方式来传递的,因此所创建的每个新对象实体都没有一份属于自身原型的副本,这也就意味着可以随时修改prototype属性,并且同意构造器创建的所有对象的prototype属性也都会同时发生改变。(甚至可以影响在修改之前就已经创建好了的对象)
5.利用自身属性重写原型属性
如果一个对象自身属性中没有找到想要的属性,就会使用原型链中查找到的相关的属性。但是,如果遇上对象的自身属性与原型属性同名又该如何处理?答案是对象的自身属性的优先级高于原型属性。
function Get(name){
this.name = name;
}
>Get.prototype.name = "zhangsan";
创建一个新对象,并访问该对象自身的name属性:
var toy = new Get("lisi");
>toy.name;
>lisi
可以看到,自身属性将原型属性的值覆盖了,或者说,访问的自身属性的优先级是高于原型属性的。
此时,可以试着删除自身属性看看:
delete toy.name;
>toy.name:
>zhangsan
此时访问的就是原型属性的值了,当然,可以随时新建一个同名的自身属性重写原型属性。