高级Javascript---原型和原型继承
在 JavaScript 中,PRototype是函数的一个属性,同时也是由构造函数创建的对象的一个属性。函数的原型为对象。它主要在函数用作构造函数时使用。
function Vehicle(wheels, engine) { this.wheels = wheels; this.engine = engine;}
在上面的示例中,Vehicle函数的原型是使用Vehicle构造函数实例化的任何对象的原型。
使用原型添加属性和方法可以使用prototype属性向对象添加属性和方法,甚至于已创建的对象也是如此:
var testVehicle = new Vehicle(2, false);Vehicle.prototype.color = "red";var testColor = testVehicle.color;
testColor的值为“red”。
你甚至可以向预定义的对象添加属性和方法。例如,你可以在String原型对象上定义一个Trim方法,脚本中的所有字符串都将继承该方法。
String.prototype.trim = function(){ // Replace leading and trailing spaces with the empty string return this.replace(/(^/s*)|(/s*$)/g, "");}var s = " leading and trailing spaces ";// Displays " leading and trailing spaces (35)"window.alert(s + " (" + s.length + ")");// Remove the leading and trailing spacess = s.trim();// Displays "leading and trailing spaces (27)"window.alert(s + " (" + s.length + ")");
prototype对象可用于从一个对象派生另一个对象。例如,你可以使用Object.create函数派生使用我们之前定义的Vehicle对象的原型(以及所需的任何新属性)的新对象Bicycle。
var Bicycle = Object.create(Object.getPrototypeOf(Vehicle), { "pedals" :{value: true}});
Bicycle对象具有属性wheels、engine、color和pedals,并且其原型为Vehicle.prototype。JavaScript 引擎会查找Bicycle的pedals属性,并查看原型链以便查找Vehicle的wheels、engine和color。
在 Internet Explorer 11 中,可以通过__proto属性用新原型替换对象或函数的内部原型。使用此属性时,将继承新原型的属性和方法以及其原型链中的其他属性和方法。
以下示例演示如何更改对象的原型。此示例演示当更改对象原型时,对象的继承属性将如何更改。
function Friend() { this.demeanor = "happy";}function Foe() { this.demeanor = "suspicious";}var friend = new Friend();var foe = new Foe();var player = new Object();player.__proto__ = foe;friend.ally = "Tom";if (console && console.log) { console.log(player.demeanor === "happy" ); // Returns false console.log(player.demeanor === "suspicious"); // Returns true console.log(player.ally === "Tom"); // Returns false // Turn the foe to a friend. player.__proto__ = friend; console.log(player.demeanor === "happy"); // Returns true console.log(player.demeanor === "suspicious"); // Returns false console.log(player.ally === "Tom"); // Returns true}
上面是摘自http://msdn.microsoft.com/zh-cn/library/hh924508(v=vs.94).aspx上的原文。
下面是我从慕客网上看到的一个问题,仔细分析之后感觉挺有意思,于是记下录来。
仔细分析Man.prototype = new People 与 Man.prototype = People.prototype 这两种继承的区别
function People (){ this.name = 'frog'; this.age = 29; } People.prototype.getName = function(){ return this.name; } function Man(){ this.name = 'rat'; this.age = 3; } Man.prototype = People.prototype; //某一天,新来的小伙伴修改了这个方法 Man.prototype.getName = function(){ return this.age; } var p = new People; var n = p.getName(); console.log(n); // 输出29而不是 frog //说明直接用原开链,父类会被子类影响
所以一般不直接用对象原型,而是用对象的实例
function People (){ this.name = 'frog'; this.age = 29; } People.prototype.getName = function(){ return this.name; } function Man(){ this.name = 'rat'; this.age = 3; } Man.prototype = new People; //再次修改原型上的方法 Man.prototype.getName = function(){ return this.age; } var p = new People; var n = p.getName(); console.log(n); // frog 说明父类没有受影响
这样改,子类的修改就不会影响到父类了,不过这样做有一个缺点,一是每次实例化Man的时候都会new People, 二是People上的属性也会继承到Man上来,通常我们只想要继承父对象上的方法,不需要它的属性,所以,就出现了下面的用法
f = function(){};f.prototype = People.prototype;Man.prototyep = new f();
通过这样中转一下,就可以只继承People上的方法,而不承它的属性,同时子类的修改,不会影响到父类了。如果您觉得这文章对您有帮助,请点击【推荐一下】,想跟我一起学习吗?那就【关注】我吧!
新闻热点
疑难解答