js 基于函数伪造的方式实现继承
2016-05-03 10:40
232 查看
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="application/javascript"> //基于伪装的继承 /** * call方法: 语法:call([thisObj[,arg1[, arg2[, [,.argN]]]]]) 定义:调用一个对象的一个方法,以另一个对象替换当前对象。 说明: call 方法可以用来代替另一个对象调用一个方法。call 方法可将一个函数的对象上下文从初始的上下文改变为由 thisObj 指定的新对象。 如果没有提供 thisObj 参数,那么 Global 对象被用作 thisObj。 */ function Parent(){ this.color = ["red","blue"]; this.name = "Leon"; } function Child(){ //在Child中的this明显应该是指向Child的对象 //当调用Parent方法的时候,而且this有时指向了Child //此时就等于在这里完成this.color = ["red","blue"] //也就是等于在Child中有了this.color的属性,这样也就变相的完成了集成 Parent.call(this); //这种调用方式,Parent的上下文是Parent对象,根本无法实现继承 //Parent(); } var c1 = new Child(); c1.color.push("green"); console.info(c1.color); //["red", "blue", "green"] var c2 = new Child(); console.info(c2.color); //["red", "blue"] console.info(c2.name); //Leon function Parent2(name){ this.color = ["red","blue"]; this.name = name; } function Child2(name , age){ //在Child中的this明显应该是指向Child的对象 //当调用Parent方法的时候,而且this有时指向了Child //此时就等于在这里完成this.color = ["red","blue"] //也就是等于在Child中有了this.color的属性,这样也就变相的完成了集成 this.age = age; Parent2.call(this , name); //这种调用方式,Parent的上下文是Parent对象,根本无法实现继承 //Parent(); } var c3 = new Child2("Leon" , 12); c3.color.push("green"); console.info(c3.color); //["red", "blue", "green"] console.info(c3.name + " " + c3.age); //Leon 12 var c4 = new Child2("Ada" , 22); console.info(c4.color); //["red", "blue"] console.info(c4.name + " " + c4.age); //Ada 22 //这个例子中的意思就是用 add 来替换 sub,add.call(sub,3,1) == add(3,1) ,所以运行结果为:alert(4); // 注意:js 中的函数其实是对象,函数名是对 Function 对象的引用。 function add(a,b){ console.info(a+b); } function sub(a,b){ console.info(a-b); } add.call(sub,3,1); //4 //call 的意思是把 animal 的方法放到cat上执行,原来cat是没有showName() 方法,现在是把animal 的showName()方法放到 cat上来执行,所以this.name 应该是 Cat function Animal(){ this.name = "Animal"; this.showName = function(){ console.info(this.name); } } function Cat(){ this.name = "Cat"; } var animal = new Animal(); var cat = new Cat(); //通过call或apply方法,将原本属于Animal对象的showName()方法交给对象cat来使用了。 //输入结果为"Cat" animal.showName.call(cat,","); //Cat animal.showName.apply(cat,[]);//Cat // Animal.call(this) 的意思就是使用 Animal对象代替this对象,那么 Cat中不就有Animal的所有属性和方法了吗,Cat对象就能够直接调用Animal的方法以及属性了. function Animal2(name){ this.name = name; this.showName = function(){ console.info(this.name); } } function Cat2(name){ Animal2.call(this, name); } var cat2 = new Cat2("Black Cat"); cat2.showName();//Black Cat // //实现多继承 // 很简单,使用两个 call 就实现多重继承了 // 当然,js的继承还有其他方法,例如使用原型链,这个不属于本文的范畴,只是在此说明call 的用法。 // 说了call ,当然还有 apply,这两个方法基本上是一个意思,区别在于 call 的第二个参数可以是任意类型,而apply的第二个参数必须是数组,也可以是arguments // 还有 callee,caller.. function Class10(){ this.showSub = function(a,b){ console.info(a-b); } } function Class11() { this.showAdd = function(a,b){ console.info(a+b); } } function Class2(){ Class10.call(this); Class11.call(this); } var c2 = new Class2(); c2.showSub(1,2); c2.showAdd(1,2); </script> </head> <body> </body> </html>
基于伪造继承问题:
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="application/javascript"> //基于伪造的继承存在问题: function Parent2(name){ this.color = ["red","blue"]; this.name = name; } //由于使用伪造的方式,不会完成Child的原形指向Parent,所以say方法不存在, 18 //解决方法:将该say方法放入到Parent2中使用this来创建, 19 // 但是又有新问题:每个对象中又存在say方法,这样空间占用太大,所有也不会单独的方式实现 Parent2.prototype.say = function(){ console.info(this.name); } function Child2(name , age){ //在Child中的this明显应该是指向Child的对象 //当调用Parent方法的时候,而且this有时指向了Child //此时就等于在这里完成this.color = ["red","blue"] //也就是等于在Child中有了this.color的属性,这样也就变相的完成了集成 this.age = age; /* * 使用伪造的方式就可以吧自雷的构造函数参数传递到父类中 */ Parent2.call(this , name); //这种调用方式,Parent的上下文是Parent对象,根本无法实现继承 //Parent(); } var c3 = new Child2("Leon" , 12); c3.color.push("green"); console.info(c3.color); //["red", "blue", "green"] console.info(c3.name + " " + c3.age); //Leon 12 c3.say(); //异常: Uncaught TypeError: c3.say is not a function var c4 = new Child2("Ada" , 22); console.info(c4.color); //["red", "blue"] console.info(c4.name + " " + c4.age); //Ada 22 </script> </head> <body> </body> </html>
解决伪造继承的问题;
<!DOCTYPE html> <html> <head lang="en"> <meta charset="UTF-8"> <title></title> <script type="application/javascript"> /** * 组合的实现方式是属性通过伪造的方法实现,方法通过原形连的方式实现 * */ function Parent(name){ this.color = ["red","blue"]; this.name = name; } Parent.prototype.ps = function(){ console.info(this.name + "[ " + this.color + "]"); } function Child(name , age){ Parent.call(this,name); this.age = age; } Child.prototype = new Parent(); Child.prototype.say = function(){ console.info(this.name + " " + this.age + " " + this.color); } var c1 = new Child("Leon" , 22) ; c1.color.push("green"); c1.say(); //Leon 22 red,blue,green c1.ps(); //Leon[ red,blue,green] var c2 = new Child("Ada" , 23) ; c2.say(); //Ada 23 red,blue </script> </head> <body> </body> </html>
相关文章推荐
- js 判断对象是否是字符串
- JavaScript 开发进阶:理解 JavaScript 作用域和作用域链
- js文件调用后台程序
- JS通过正则限制 input 输入框只能输入整数、小数(金额或者现金) 两位小数
- JS DOM常用对象的属性和方法
- js选择器的兼容
- d3.js——csv表格的读取
- 制作动画或小游戏——CreateJS基础类(一)
- 跨域的三种方法总结:代理,JSONP,以及XHR2
- JS基于clipBoard.js插件实现剪切、复制、粘贴
- webdriver 执行js
- 《高性能JavaScript》摘要
- 什么是JS事件冒泡
- JS实现判断滚动条滚到页面底部并执行事件的方法
- jsp include中文乱码问题解决方案
- JavaScript arguments 对象
- Javascript验证和限制文本框只能输入数字或者小数
- js后台提交成功后 关闭当前页 并刷新父窗体(转)
- Alamofire post header json
- Alamofire post json