第5章 原型
5.1 原型属性
function f(a,b){return a*b;};// length 属性f.length; //2// constructor 构造属性f.constructor; // function Function() { [native code] }// prototype 属性 初始值是空对象typeof f.prototype; //"object"
5.1.1 利用原型添加方法和属性
function f1(name,color){// 使用this添加属性this.name=name;this.color=color;this.whatAreYou=function(){return 'I am a'+this.color+''+this.name;};}// 使用prototype属性添加属性和方法f1.prototype.price=100;f1.prototype.rating=3;f1.prototype.getInfo=function (){return 'Rating: '+this.rating+',price: '+this.price;};
5.1.2 使用原型的属性和方法
function f1(name,color){// 使用this添加属性this.name=name;this.color=color;this.whatAreYou=function(){return 'I am a'+this.color+''+this.name;};}// 使用prototype属性添加属性和方法f1.prototype.price=100;f1.prototype.rating=3;f1.prototype.getInfo=function (){return 'Rating: '+this.rating+',price: '+this.price;};var f2=new f1('webcam','black');f2.color; // "black"f2.getInfo(); //"Rating: 3,price: 100"// 修改prototype属性,由同一构造器创建的所有对象的prototype属性也都会同时发生改变(会影响在修改之前已经创建的对象)f1.prototype.get=function(what){return this[what];}f2.get('price'); // 100
5.1.4 利用自身属性重写原型属性
对象自身属性的优先级高于原型属性
function F1(name){this.name=name;};F1.prototype.name='Alen';var f2=new F1('XiaoMing');f2.name; // "XiaoMing" 不是 Alen// 使用hasOwnProperty()判断一个属性是自身属性还是原型属性f2.hasOwnProperty('name'); //true//删除自身属性后,原型属性才会显示delete f2.name; // truef2.name; // "Alen"
5.1.5 isPrototypeOf()方法
isPrototypeOf():当前对象是否为另一个对象的原型
var person={like:'eat',age:12,sex:'boy'};function F1(name){this.name=name;}F1.prototype=person;var f2=new F1('Alen');// 判断person是否为f2的原型person.isPrototypeOf(f2); //true//使用getPrototypeOf()获取原型Object.getPrototypeOf(f2)===person; //true
5.1.6 神秘的__proto__链接
5.2 扩展内建对象
内建对象的构造器函数可以通过其原型来进行扩展。
1 <script type="text/javascript"> 2 // 示例1:扩展Array的内建函数,用来查询数组中是否存在某个特定的值 3 Array.prototype.inArray=function(needle){ 4 for (var i = 0; i < this.length; i++) { 5 if(this[i]===needle){ 6 return true; 7 }else{ 8 return false; 9 } 10 }; 11 }; 12 var colors=['red','black','blue']; 13 colors.inArray('red'); //true 14 colors.inArray('green'); //false 15 //示例2:反转字符串 16 // 先利用split()将目标字符串转换成数组,然后调用该数组的reverse()方法产生一个反向数组。
// 最后通过join()方法将结果数组转换为字符串 17 String.prototype.reverse=function (){ 18 return Array.prototype.reverse.apply(this.split('')).join(''); 19 }; 20 "bums".reverse(); //smub 21 </script>
5.2.1 关于内建对象的讨论
如果想通过原型为某个对象添加一个新属性,务必检查一下该属性是否已经存在。
5.2.2 原型陷阱
注意: 1> 当对原型对象执行完全替换时,可能会触发原型链中某种异常
2> prototype.constructor 属性不可靠
1 <script type="text/javascript"> 2 function Dog(){ 3 this.tail=true; 4 }; 5 var f1=new Dog(); 6 var f2=new Dog(); 7 // 仍可以为Dog()的原型添加属性,添加之前已经存在的对象也可访问新属性 8 Dog.prototype.say=function(){ 9 return 'worf'; 10 }; 11 // f1、f2可以访问新方法 12 f1.say(); //"worf" 13 f2.say(); //"worf" 14 // 检查对象的构造器 15 f1.constructor === Dog; // true 正常 16 f2.constructor === Dog;// true 正常 17 Dog.prototype.constructor === Dog; // true 18 19 // 用自定义新对象完全覆盖掉原有的原型对象 20 Dog.prototype={ 21 paws:4, 22 hair:true 23 }; 24 // 这样原有对象不能访问新属性,但通过__proto__与原有的原型保持联系 25 f1.paws; //undefined 26 f1.say(); //"worf" 27 typeof f1.__proto__.say; // "function" 28 // 之后创建的对象室友被更新后的prototype对象 29 var f3=new Dog(); 30 f3.say(); // f3.say is not a function 31 f3.tail; // true 32 f3.paws; // 4 33 // __proto__指向新的原型对象 34 f3.__proto__.hair; //true 35 36 // 新对象的constructor属性不在保持正确 37 f3.constructor;// function Object() { [native code] } 38 // 本应该指向Dog(),现在指向Object 39 f1.constructor; //function Dog(){this.tail=true;} 仍为Dog() 不变 40 Dog.prototype.constructor; // function Object() { [native code] } 41 //重新设置constructor属性 解决 42 Dog.prototype.constructor=Dog; 43 new Dog().constructor === Dog; // true 44 </script>