js中call的使用问题

function Person(name,age){
    this.name = name;
    this.age = age;
}

Person.prototype = {
    sayName : function(){
        return "my name is " + this.name;
        //alert(this.name)
    },
    sayAge : function(){
        return "I'am " + this.age + " old";
    }
}

var person = new Person("leo",29);

lisi = {
    name : "lisi"    
}

person.sayName.call(lisi);
alert(lisi.sayName());    // lisi.sayName is not a function

为什么呢?是我写法的问题吗?

第二个问题:
person.sayName.call(lisi)跟Person.call(lisi)的区别是什么?
我的理解是:后者借用了Person全部的属性跟方法,而前者只是借用了sayName方法而已。(我的理解好像是错的~55555)
阅读 3.5k
4 个回答

看完题主修改后的提问,终于知道问题在哪了:不是改变lisi的this让他拥有sayName,而是改变person.sayName的this,使得其能够访问lisi.name


alert(lisi.sayName()); // lisi.sayName is not a function

这很对啊,你之前不都写明了么,lisi只有一个属性name,哪来的sayName()
我不知道你是不是受到网上某些奇怪教程的影响,反正我看到过有一个教程把call等价为将Person中的代码复制到lisi里去了,这种“等价”显然是错的

Func.call(Obj)的用处是将Func置于Obj的上下文中去执行。简单来说,就是在执行Func假装当作Func是在Obj内部的一样,从而使Fun拥有访问Obj属性的能力

call和apply只是借用其他对象的方法,并不是给某个对象新增方法,所以调用时候提示没有sayname方法

person.sayName.call(lisi)  //这句话返回lisi

但是此时lisi这个对象里面还是没有sayName这个方法啊。

你可以理解call这个方法只是暂时性的给lisi借用了person.sayName方法。

之前没有看到sayName在原型上定义。抱歉。

person.prototype上确实有sayName的方法,可是这跟lisi没有任何关系。想要让lisi也有sayName的方法,就得让lisi继承自Person.prototype。实例里面访问原型有一个属性,__proto__,所以,可以这样修正。

lisi.__proto__ = Person.prototype

这样lisi和person就是兄弟关系。都拥有原型上的sayName方法。

顺便说一点。重写了Person.prototype,请一定记得加上constructor属性。


之前的回答:

解决方案。可以使用bind注册一个全局的方法。

var sayName = person.sayName.bind(lisi);
sayName();   //lisi

或者使用bind返回一个通用的函数。

var sayName = Function.prototype.call.bind(person.sayName);
sayName(lisi)  //lisi
sayName(person)  //leo
Person.sayName.call(lisi)跟Person.call(lisi)的区别是什么?

这两种并没有什么区别。能有什么区别呢?同样都是函数调用call方法。

function.call(obj,param1,param2...)就是调用function并把function里的this替换成obj,调用参数就是param1,param2...
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题