每个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;