<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>原型属性prototype</title>
<meta name="description" content="">
<meta name="keywords" content="">
<style type="text/css">
</style>
</head>
<body>
<script type="text/javascript">
//一、利用原型添加方法与属性
//1、创建一个构造器函数Gadget()
function Gadget(name,color){
this.name=name;
this.color=color;
this.whatAreYou=function(){
return "I am a "+this.color+" "+this.name;
};
}
//2、为上面的构造器增加两个属性(price和rating)和方法(即getInfo())
Gadget.prototype.price=100;
Gadget.prototype.rating=3;
Gadget.prototype.getInfo=function(){
return 'Rating:'+this.rating+',price:'+this.price;
};
//3、使用原型的方法与属性
var newtoy=new Gadget('webcam','black');
newtoy.name; //webcam
newtoy.color;//black
newtoy.whatAreYou();
newtoy.price; //100
newtoy.rating; //3
newtoy.getInfo(); // Rating: 3,price: 100
/*4、由于在javascript中几乎所有对象都是通过传递引用的方式来传递的,
因此、我们所创建的每个新对象实体中并没有一份属于自己原型副本。
这也就意味着我们可以随时修改prototype属性,并且由同一构造器创建
的所有对象的prototype属性也都会同时改变(甚至还会影响在修改之前就已经创建的那些对象)*/
Gadget.prototype.get=function(what){
return this[what];
}
//即便newtoy对象在get()方法定义之前就已经被创建了,但我们依然可以在该对象中访问对象新增的方法
newtoy.get('price'); //100
newtoy.get('color'); //black
//二、自身属性与原型属性
/*当我们访问newtoy的某个属性时,例如:newtoy.name时,javascript引擎会遍历该对象的所有属性,
并查找出name属性。如果找到了就会立即返回其值。如果饿哦们访问rating属性时,javascript引擎依然会查询
newtoy对象的所有属性,但是这一回它找不到一个叫rating的属性了。接下来,脚本引擎就会去查询用于创建当前
对象的构造器函数的原型(等价于我们直接访问newtoy.constructor.prototype)。如果在原型中找到了该属性,就
立即使用该属性。
首先、我们知道每个对象都会有一个构造器,而原型本身也是一个对象,这意味着它必然也有一个构造器,
而这个构造器又会有自己的原型。于是这张结构可能会一直不断地持续下去,并最终取决于原型链的长度,
但其最后一环肯定是内建对象,因为它是最高级的父级对象。*/
//三、利用自身属性重写原型属性
// 1、对象自身的属性的优先级高于原型属性
Gadget.prototype.name='mirror';
var toy=new Gadget('camera');
toy.name; //camera
//通过hasOwnProperty()方法判断一个属性是自身属性还是原型属性
toy.hasOwnProperty('name');//true
//删除自身这个属性,同名的原型属性就会"浮出水面"
delete toy.name; //true
toy.name; //"mirror"
toy.hasOwnProperty('name'); //false
//我们可以随时重建这个自身属性:
toy.name='camera';
toy.name; //camera
//2、hasOwnProperty()方法也可以判断某个原型属性是哪个原型对象的。
toy.toString(); //[object Object]
toy.hasOwnProperty('toString'); //false
toy.constructor.hasOwnProperty("toString"); //false
toy.constructor.prototype.hasOwnProperty("toString");//false
Object.hasOwnProperty("toString");// false
Object.prototype.hasOwnProperty("toString");//true
//四、枚举属性(使用for in)
/*1、并不是所有的属性都会在for-in循环中显示。例如(数组的)length属性和constructor属性就不会被显示。
那些会显示的属性被称为是可枚举的,我们可以通过各个对象所提供的propertyIsEnumerable()方法来判断
对象的某个属性是否可枚举。
2、原型链中的各个原型属性也会被显示出来,当然前提是它们是可枚举的。我们可以通过对象的
hasOwnProperty()方法来判断一个属性是对象自身属性还是原型属性。
3、对于所有的原型属性,propertyIsEnumerable()都会返回false,包括那些在for-in循环中可枚举的属性。*/
newtoy=new Gadget('webcam','black');
//propertyIsEnumerable()该方法会对所有的非内建对象返回true
newtoy.propertyIsEnumerable('name'); //true
//而对于內建属性和方法来说,它们大部分都是不可枚举的:
newtoy.propertyIsEnumerable('constructor');// false
//任何来自原型链中的属性也是不可枚举的
newtoy.propertyIsEnumerable('price');//false
//但是需要注意的是、如果propertyIsEnumerable()的调用是来自原型链上的某个对象
//那么该对象中的属性是可以枚举的。
newtoy.constructor.prototype.propertyIsEnumerable('price'); //true
//五、isPrototypeOf()方法
//每个对象都会有一个isPrototypeOf()方法,这个方法会告诉我们当前对象是否是另一个对象
//的原型
var monkey={
hair: true,
feeds: 'bananas',
breathes: 'air'
};
//创建Human()构造器,并将其原型属性设置为monkey
function Human(name){
this.name=name;
}
Human.prototype=monkey;
var george=new Human('George');
monkey.isPrototypeOf(george); //true
//获得对象的原型:getPrototypeOf()方法
Object.getPrototypeOf(george).feeds; //banana
Object.getPrototypeOf(george)===monkey; //true
//六、_proto_链接
//在现代javascript环境中,对象中确实存在一个指向相关原型的链接,
//这个神秘的链接被叫做_proto_属性(proto这个词的两边各有两条下划线)
var developer=new Human();
developer.feeds="pizza";
developer.hacks="javascript";
developer._proto_===monkey; //true(在ie之类的浏览器中_proto_是不存在的)
//_proto_与prototype并不是等价的。_proto_实际上是某个实例对象的属性,
//而prototype则是属于构造器函数的属性。
typeof developer._proto_;//object
typeof developer.prototype;// undefined
typeof developer.constructor.prototype; //object
//七、关于原型的总结
/*
* 1、在javascript中,所有函数都会拥有一个叫做prototype的属性,默认初始值
* 为"空"对象(没有自身属性的对象)
* 2、我们可以在相关的原型中添加新的方法和属性,甚至可以用自定义对象来完全
* 替换掉原有的原型属性。
* 3、当我们通过某个构造器函数来新建时(使用new操作符),这些对象就会自动拥有
* 一个指向各自prototype属性的神秘链接,并且可以通过它来访问相关原型对象的
* 属性。
* 4、对象自身属性的优先级要高于其原型对象中的同名属性
* 5、我们可以通过hasOwnPrototype()方法来区分对象自身属性和原型属性
* 6、原型链的存在:如果我们在一个对象foo中访问一个并不存在的属性bar,
* 即当我们访问foo.bar时,javascript引擎就会搜索该对象的原型的bar属性。
* 如果依然没有找到bar属性,则会继续搜索其原型的原型,以此类推,知道搜索
* 到Object.prototype。
* 7、我们可以对內建的构造器函数进行扩展,以便所有的对象都能引用我们添加
* 的功能。如果将某个函数赋值给Array.prototype.flip,所有的数组对象都能立即
* 添加一个flip()方法,如[1,2,3].flip()。另外,在添加相关的方法和属性之前,
* 应该做一些对已有方法的检测工作,这将会大大增加脚本对于未来环境的适应力
*
*
* */
</script>
</body>
</html>
javascript原型prototype
最新推荐文章于 2016-11-18 15:26:16 发布