JavaScript的原型原型链的深刻理解及运用
2017-03-25 19:24
567 查看
*今天总结一下JavaScript的prototype原型和*____proto____原型链,了解这俩对我们深刻理解 js ,封装常用小技巧很有帮助。
ES5中js本身是没有类的,在ES5中js类就是函数function,而function本身也是对象。
一、js中的继承是通过原型链 __proto__来实现的,对象与对象以及原型prototype(也是对象)就是通过__proto__原型链来来链接的,具体过程我们来上代码说明。
这一段代码格式应该很常见,不过有个问题,var obj1 =new obj(“laowang”)是在全局作用域中的,如果页面这种写法比较多 ,很容易勿让污染全局。
可以写成这样:
回到正题, 当我们执行 执行下列代码时:
我们会看到 obj1 拥有了obj 的属性和方法,也拥有了obj原型的方法。
分析:obj目前有name 和age 私有属性和fun的私有方法,我们在obj原型上添加了 city属性,和fun1方法
而我们用new创建的构造函数,并赋给对象obj1,这个过程js为我们做了类似:(此处代码仅说明道理)
说明obj1的原型链指向obj的原型
需要说明一点,用new构造的函数,是没有原型的 例如:
二、上面的说完了,但是还有个问题,如果我想创建一个函数myObj;让该函数拥有obj原型的方法和属性该怎么办。
1.首先你可能会这样做:
这是因为 myObj的原型中的__proto__指向了obj的原型。myObj并没有实现继承obj的原型方法和属性, 并且还会带来一个问题是,当你修改myObj原型中的属性(city)或方法( fun1)时,obj1和obj2中 属性(city)和方法(fun1)也会跟着改变。
2.或者你有这样改了:
但是带来的问题是
3.正确的写法应该这样写:
此时myObj的原型对象就拥有了obj的原型方法和属性,并且当myObj的原型属性和方法改变是 ,不会影戏obj原型的属性和方法
但是此时还有几个问题:
1. myObj.prototype.constructor 返回的是实例obj,本身constructor是原型中指向自己的实例的,而此时,myObj.prototype.constructor和obj.prototype.constructor都指向实例obj;
2. myObj.city 结果会是 underfind; 我们只能通过访问 myObj的原型去访问city属性;
3. 如果第二个问题解决了,我们会发现myObj.fun1(); 结果是underfind;
好下来咱们一个一个解决
第一个问题:我们可以这样
第二个问题:我们可以这样:
第三个问题:我们可以这样:
好了问题基本解决了,最后我放上所有代码
好了,到这里就结束了,,如果有什么错误,欢迎留言指点。
ES5中js本身是没有类的,在ES5中js类就是函数function,而function本身也是对象。
一、js中的继承是通过原型链 __proto__来实现的,对象与对象以及原型prototype(也是对象)就是通过__proto__原型链来来链接的,具体过程我们来上代码说明。
function obj (name){ this.name=name, this.age="23" this.fun=function(){ return this.name }; obj.prototype.city="china"; }; obj.prototype.fun1=function(){ return this.age; }; var obj1= new obj("laowang"); var obj2= nwe obj("hello");
这一段代码格式应该很常见,不过有个问题,var obj1 =new obj(“laowang”)是在全局作用域中的,如果页面这种写法比较多 ,很容易勿让污染全局。
可以写成这样:
(function(){ var obj1 = new obj("laowang"); //这样也能正常运行,而且不被污染全局环境 })()
回到正题, 当我们执行 执行下列代码时:
obj1.name; //结果 laowang obj1.city; //结果 China obj1.fun(); //结果 laowan 4000 g obj1.fun2(); //结果 23
我们会看到 obj1 拥有了obj 的属性和方法,也拥有了obj原型的方法。
分析:obj目前有name 和age 私有属性和fun的私有方法,我们在obj原型上添加了 city属性,和fun1方法
obj.prototype.city="china"; obj.prototype.fun1=function(){ return this.age; };
而我们用new创建的构造函数,并赋给对象obj1,这个过程js为我们做了类似:(此处代码仅说明道理)
var obj1= (function(){ var o={}; //创建一个新对象 o.__proto__=obj.prototype; //将新对象的原型链指向obj的原型 obj.call(o,"hello") //执行obj函数,将o对象指针指向obj函数,及o拥有了obj原型的属性和方法(引用) return o; })() //我们可以尝试一下, obj1.__proto__===obj.prototype // 结果true (__proto__非标准IE不支持,标准Object.getPrototypeOf()方法)
说明obj1的原型链指向obj的原型
__proto__方法非获取实例原型的标准方法,标准方法请使用
Object.getPrototypeOf()来获取实例原型
obj1.name===obj2.name //结果 true 说明obj1和obj2共同引用obj的属性name
需要说明一点,用new构造的函数,是没有原型的 例如:
obj1.prototype //结果 underfind 证实了我们的猜想
二、上面的说完了,但是还有个问题,如果我想创建一个函数myObj;让该函数拥有obj原型的方法和属性该怎么办。
1.首先你可能会这样做:
var myObj = function (){}; myObj.prototype=obj.prototype; myObj.city //结果 underfind
这是因为 myObj的原型中的__proto__指向了obj的原型。myObj并没有实现继承obj的原型方法和属性, 并且还会带来一个问题是,当你修改myObj原型中的属性(city)或方法( fun1)时,obj1和obj2中 属性(city)和方法(fun1)也会跟着改变。
2.或者你有这样改了:
myObj.__proto__=obj.prototye
但是带来的问题是
__proto__是不标准的,在ie和火狐上有时会报错。
3.正确的写法应该这样写:
Object.creat=function (aa) { var o = function(){}; //创建新函数 o.prototype=aa; //让该函数的原型等于obj的原型 return new o(); //返回一个o的构造函数 } myObj.prototype=Object.creat(obj.prototye); // 让函数的原型等与Objet.creat对象,
此时myObj的原型对象就拥有了obj的原型方法和属性,并且当myObj的原型属性和方法改变是 ,不会影戏obj原型的属性和方法
但是此时还有几个问题:
1. myObj.prototype.constructor 返回的是实例obj,本身constructor是原型中指向自己的实例的,而此时,myObj.prototype.constructor和obj.prototype.constructor都指向实例obj;
2. myObj.city 结果会是 underfind; 我们只能通过访问 myObj的原型去访问city属性;
3. 如果第二个问题解决了,我们会发现myObj.fun1(); 结果是underfind;
好下来咱们一个一个解决
第一个问题:我们可以这样
myobj.prototype.constructor=myObj; //让myObj的原型constructor指向myObj本身。
第二个问题:我们可以这样:
var ob= new myobj(); //在用 new 创建一个新实例。
第三个问题:我们可以这样:
var myObj = function () { obj.call(this); //解决ob.fun1() underfind };
好了问题基本解决了,最后我放上所有代码
function obj (name){ this.name=name, this.age="23" this.fun=function(){ return this.name }; obj.prototype.city="china"; }; obj.prototype.fun1=function(){ return this.age; }; var obj1= new obj("laowang"); var obj2= new obj("hello"); // new构造函数内的操作(代码仅说明) // obj1=(function(){ // var o={}; // o.__proto__=obj.prototype; // obj.call(o,"hello") // return o; // })(); var myObj = function () { obj.call(this); //解决ob.fun1() underfind }; Object.create=function(aa){ var o = function(){}; o.prototype=aa; return new o(); } myObj.prototype=Object.create(obj.prototype); // 纠正myObj原型的constructor的指向 myobj.prototype.constructor=myObj; // 解决用ob.city直接访问 var ob= new myobj();
好了,到这里就结束了,,如果有什么错误,欢迎留言指点。
相关文章推荐
- 深刻理解JavaScript基于原型的面向对象
- 深入理解JavaScript系列(5):强大的原型和原型链
- 理解javascript中的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 学习javascript面向对象 理解javascript原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 理解javascript中的原型和原型链
- <深入理解JavaScript>学习笔记(5)_强大的原型和原型链
- javascript关于原型的深刻理解
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列 ----(5):强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深入理解JavaScript系列(6) 强大的原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链
- 深刻理解JavaScript基于原型的面向对象
- 深入理解JavaScript系列(5):强大的原型和原型链
- 学习javascript面向对象 理解javascript原型和原型链
- 深入理解JavaScript系列(5):强大的原型和原型链