方法借用 2. 设置方法中 this 的指向
- var obj1 = {
- name:"Neld",
- age:10,
- showInfo:function () {
- console.log("name:"+this.name,"age:"+this.age);
- }
- }var obj2 = {
- name:"Lily",
- age:12
- }
- obj1.showInfo();//name:Neld age:10
- obj2.showInfo();//obj2.showInfo is not a function
obj1 对象中有 showInfo 方法, 而 obj2 对象中没有, 所以如果直接使用 obj2 调用 showInfo 方法的时候抛出错误信息.
如果我们临时需要使用 obj2 调用 showInfo 方法来打印出 name 和 age 属性的值, 此时可以使用这里的 call 或者 apply 方法来实现.
- obj1.showInfo.call(obj2);//name:Lily age:12
- obj1.showInfo.apply(obj2);//name:Lily age:12
这就是把 obj1 中的 showInfo 方法借用给 obj2 使用.
同时我们观察到, 在 showInfo 方法中使用到了 this 关键字, 在 obj2 借用该方法的时候, 其中的 this 已经指向了 obj2 对象, 这就要达到修改方法中 this 关键字的指向的目的.
call 和 apply 方法的作用是完全一样的, 那么他们的区别是什么呢? 继续往下分析.
- var obj1 = {
- name:"Neld",
- age:10,
- add : function (a, b) {
- return a + b;
- }
- }var obj2 = {
- name:"Lily",
- age:12
- }console.log(obj1.add.call(obj2, 1, 2));//3//console.log(obj1.add.apply(obj2, 1, 2));//CreateListFromArrayLike called on non-objectconsole.log(obj1.add.apply(obj2, [2, 2]));//4
在 obj1 中定义一个带有两个参数的方法, obj2 中没有, 问题一样, obj2 也要使用到 obj1 中的 add 方法, 此时使用 call 或者 apply 借用即可.
此时新的问题是, 在调用 add 方法的时候参数应该如何传递?
call 方法:
? 将 this 指向的对象作为第一个参数, 其他参数依次传递即可
apply 方法:
? 将 this 指向的对象作为第一个参数, 其他参数封装到数组中传递
? 如果没有使用数组, 程序报错.
以上就是 call 和 apply 的基本使用, 这两个方法在后续的课程中会大量的使用到, 所以必须引起重视.
借用构造函数继承说明
所谓借用构造函数, 就是在子构造函数中调用父构造函数, 达到继承并向父构造函数传参的目的.
- function SuperClass(name,age) {
- this.name = name;
- this.age = age;
- }
- SuperClass.prototype.fun1 = function () {
- console.log("name:",this.name,"age:",this.age);
- }function SubClass(color) {
- this.color = color;
- }
- SubClass.prototype = new SuperClass("xxx",10);// 继承父构造函数并设置 name 和 age 的值
- SubClass.prototype.fun2 = function () {
- console.log("color:",this.color);
- }var sub = new SubClass("red", "Neld", 10);var sub2 = new SubClass("red", "Lily", 12);console.log(sub);console.log(sub2);
上面是原型链的继承, 这种方式存在一个问题是, 在创建不同对象的时候, 无法为其继承过来的成员赋值.
这里的 sub 和 sub2 两个对象的 name 和 age 属性值都是 "xxx" 和 10, 很明显是不满足我们需求的.
那么我们来看看借用构造函数是否能解决这个问题呢?
- function SuperClass(name,age) {
- this.name = name;
- this.age = age;
- }
- SuperClass.prototype.fun1 = function () {
- console.log("name:",this.name,"age:",this.age);
- }function SubClass(color, name, age) {
- this.newMethod = SuperClass;//1
- this.newMethod(name, age);//2
- this.color = color;
- delete this.newMethod;//3
- }//SubClass.prototype = new SuperClass();
- SubClass.prototype.fun2 = function () {
- console.log("color:",this.color);
- }var sub = new SubClass("red", "Neld", 10);var sub2 = new SubClass("red", "Lily", 12);console.log(sub);console.log(sub2);
1,2,3处代码是实现借用构造函数的关键. 下面一一作出解释:
1: 将父对象的构造函数设置为子对象的成员
2: 调用这个方法, 想过类似于将父构造函数的代码放在子构造函数中来执行
- function SubClass(color, name, age) {
- this.newMethod = SuperClass;
- this.name = name;// 父构造函数中的代码
- this.age = age;// 父构造函数中的代码
- this.color = color;
- delete this.newMethod;
- }
这样看应该更直观一点, 执行之后就是在为当前创建出来的对象封装 name 和 age 属性.
3: 在子构造函数中, newMethod 仅仅为了在2调用父构造函数使用, 用完之后也就没了价值, 所以, 直接删除该方法即可
可以看到, 借用构造函数继承方式解决了原型链及继承的问题.
下面再看看另外一种借用构造函数的实现方式(使用 call 或 apply):
- function SubClass(color, name, age) {
- //SuperClass.call(this,name,age);
- SuperClass.apply(this,[name,age]);
- this.color = color;
- }
我们可以使用 call 或 apply 更简单快捷的实现和上面一样的效果.
以上就是借用构造函数继承 (也要对象冒充) 的两种实现方式. 当然, 这种继承方式都存在下面两个问题:
来源: http://www.bubuko.com/infodetail-3344384.html