每個javascript函數自動prototype屬性,使用prototype可以為類聲明通用的屬性,當一個對象被創建時,構造函數將會把它的屬性的prototype賦給對象的內部屬性__proto__
另外,javascript使用prototype實現繼承機制
創建通用屬性
不采用原型時:
function Fish(name, color){ this.name = name; this.color = color; this.livePlace = "water"; this.canSwim = function(){ console.log("I can swim");}; } var cod = new Fish("cod","white"); var salmon = new Fish("salmon","black"); console.log(cod.livePlace); //water console.log(salmon.livePlace); //water console.log(salmon.canSwim == cod.canSwim); //false
此時每申明一個實例Fish,都會有相同的屬性值livePlace,有些重復,無法共享方法和屬性
使用prototype,實例可以共享屬性
function Fish(name, color){ this.name = name; this.color = color; } Fish.prototype.livePlace = "water"; Fish.prototype.canSwim = function(){ console.log("I can swim");}; var cod = new Fish("cod","white"); var salmon = new Fish("salmon","black"); console.log(cod.livePlace); console.log(salmon.livePlace); console.log(salmon.canSwim == cod.canSwim); //true
例子中 實例共享屬性livePlace和canSwim屬性
prototype 與 __proto__
1.所有函數的__proto__都指向Function.prototype
2. 對象的__proto__指向 其構造器的prototype
eg:
function Fish(name, color){ this.name = name; this.color = color; } Fish.prototype.livePlace = "water"; Fish.prototype.canSwim = function(){ console.log("I can swim");}; var cod = new Fish("cod","white"); var salmon = new Fish("salmon","black"); var object = {}; console.log(Fish.__proto__ === Function.prototype); //true console.log(cod.__proto__ === Fish.prototype); //true console.log(object.__proto__ === Object.prototype); //true
console.log(Object.getPrototypeOf(Fish) === Fish.__proto__); //true
注意: 瀏覽器不支持getPrototypeOf時可以使用Object.getPrototypeOf 替代
屬性相關方法
hasOwnProperty() :是否含有某屬性 isPrototypeOf() : 是否是..的原型 in
eg:
function Fish(name, color){ this.name = name; this.color = color; } Fish.prototype.livePlace = "water"; Fish.prototype.canSwim = function(){ console.log("I can swim");}; var cod = new Fish("cod","white"); var salmon = new Fish("salmon","black"); console.log(Fish.prototype.isPrototypeOf(salmon)); //true console.log(cod.hasOwnProperty("name")); //true console.log("livePlace" in cod); //true
使用prototype實現繼承
方式一:
//父類 function People(name,age){ this.name = name; this.age = age; this.species = "human"; this.getName = function(){ return this.name; } this.getAge = function(){ return this.age; } this.sayHello = function(){ console.log("hi,I am the father class"); } } //子類 function Children(name, age){ this.name = name; this.age = age; } Children.prototype = new People(); console.log(Children.prototype.constructor === People); //true Children.prototype.constructor = Children; var wish = new Children("wish"); console.log("the name of wish is:"+wish.getName()); //the name of wish is:wish console.log(wish.sayHello()); //hi,I am the father class
注意:
1. prototype對象包含一個contructor屬性,每一個實例也有一個constructor屬性,默認調用prototype對象的constructor屬性。Children.prototype = new People();給prototype賦了新的值, 此時Children.prototype.constructor值變為People,因而我們需要修改以保證原型鏈的正確性
2. 只要修改了prototype,一定要將新的prototype的constructor指向原來的構造函數
相關信息查看:js類型判斷及鴨式辨型
方式二:
Children.prototype = People.prototype;
Children.prototype.constructor = Children;
注意:此種方式下如果 Children.prototype做了更改時,People.prototype也會相應更改
可以使用空函數作為中間介,以改善上面兩種方式,如下:
Var F = function(){} F.prototype = People.prototype; Children.prototype = new F(); Children.prototype.constructor = Children;
