JavaScript原型
1. 原型
-
在
JavaScript
中,一切皆对象 -
对于基本数据类型,也有包装类型把它们包装成一个对象来使用
-
只要是对象,那么就一定有属性和方法
对于函数,也是对象,那么他也有属性和方法
那有什么属性呢?
函数一旦声明成功,那么每个函数对象都有一个属性prototype
这个prototype
指向的就是函数的原型对象
而原型对象中也有一个属性constructor
指向的是该函数
浏览器对于构造函数new出来的对象,也可以通过一个隐藏的属性__proto__
来找到构造函数的原型对象
注意:对于普通函数来说,原型没有用处,所以只关心构造函数的原型
如图:
那么我们在创建一个构造函数时:
function Person(name,age,sex){ this.name=name; this.age.=age; this.sex=sex; this.speak=function(){ console.log("我的名字是"+this.name); } } var p1=new Person("张三",18,"男"); var p2=new Person("李四",28,"男");
如图:对于每个由new Person出来的对象都会拥有自己一个独有的speak()方法,那么就会占据大量的内存
既然原型存储是一些公共的东西,那么我们可以将方法存入原型中,自己的属性还是存储在对象中
function Person(name,age,sex){ this.name=name; this.age.=age; this.sex=sex; } Person.proto.speak=function(){ console.log("我的名字是:"+this.name); //this 哪个对象调用这个方法,this就是谁 } var p1=new Person("张三",18,"男"); var p2=new Person("李四",28,"男");
在对象中找到了要的属性或方法,则会直接使用,如果找不到的属性或方法,浏览器会自动去他的构造函数的原型中找
如图:
p1.speak();
调用speak方法时,现在自身找有没有speak
方法,如果有直接使用,没有则顺着图中的红色线找向构造函数的原型对象中,找到了speak
方法就使用原型中的speak
方法
注意:
function Person(name,age) { this.name = name; this.age = age; } Person.prototype.speak = function () { console.log("我的名字是:"+this.name); }; Person.prototype.name="哈哈哈"; var p1 = new Person("张三",29); var p2 = new Person("李四",18); p1.__proto__.speak();
如上所示,原型中有一个name属性,属性值为哈哈哈
那么使用p1.__proto__.speak();
会输出张三还是哈哈哈呢???
答案应该是哈哈哈
因为p1.__proto__.speak();
中是p1.__proto__
在调用speak,那么this指向的就是p1.__proto__
那么this.name就会先去p1.__proto__
中找name.
另外:
function Person(name,age) { this.name = name; this.age = age; } //自己创建一个原型对象,替换默认的原型对象,这样就具有了封装性,不然一个一个方法添加到原型中就不具有封装性 Person.prototype={ constructor:Person, //将constructor指向自己 speak : function () { console.log("我的名字是"+this.name); }, eat : function () { console.log("吃吃吃"); } } var p1 = new Person("张三",19); //一定要先将原型对象替换好后才去创建一个对象,不然在之前的话就还是指向的默认的原型 var p2 = new Person("李四",28); p1.speak(); p2["eat"]();
如图: