call()的理解及其原理

693 阅读4分钟

call()

什么是call()?

call() 方法是预定义的 JavaScript 方法。

它可以用来调用所有者对象作为参数的方法。

通过 call(),您能够使用属于另一个对象的方法。

看了官方的解释一头雾水,这里简单理解下.

1.直接调用函数.

function foo(){
    console.log("move")
}
foo.call()
// => move

如图定义一个函数,通过call()方法可以直接调用该函数,既然能直接调用函数,那么在函数内部调用另一个函数也没有问题的

function foo(){
    console.log("move")
}
function bar(){
    foo.call()
}
bar()
// => move

2.修改this指向.

function foo(){
    console.log(this)
}
foo.call()
// this指向的是window对象

function foo(){
    console.log(this)
}
var fn = { move: "移动" }
foo.call(fn)
//this指向{move:"移动"} 对象

这个对比两段代码就可以明白,我们先定义了一个函数,打印下它的 this指向,第一张图指向的是它的调用者,也就是window对象;第二张图在 call()方法中添加了一个fn参数,此时再打印出来的this指向就是fn对象了.

call(thisArg,arg1,arg2) 方法可以传递三个参数,其中第一个是**this**指向的对象,后两个是值

  • 原理及模拟实现一个call方法

Function.prototype.myCall = function(context) {

context = context ? Object(context) : window

context.fn = this

let args = [...arguments].slice(1)

let r = context.fn(args)

delete context.fn

return r

}

1.上面抄了段代码过来,那个就是call()实现的原理方法.既然自己没法写出来,那就学习理解下他人的代码把.

首行定义了一个函数,与普通函数的区别就是定义在原型对象上的.这样 ​Function​的原型上就有了一个 myCall方法了 ,实际调用myCall,也就是执行那一段匿名函数了.其中context为接受来的那个参数,就是 myCall()方法括号中放的那个.此时的this指向为当前函数调用者,这里我们可以举个例子:

我们定义一个函数 ​

function foo(){

console.log("我是myCall函数调用者")

}

此时foo函数调用myCall函数时第一步的指向就是foo这个函数

2.context = context ? Object(context) : window

这一段为三目运算,判断接受来的参数是否为空,如果有参数,也就是为true,说白就是调用myCall()方法时传入了需要指向的对象.如果为空,为空的情况下出现的undefined,它的布尔值为false.true时执行表达式 2,将Obeject(context)赋值给context;false时执行表达式3,将window对象赋值给context.此时的this指向为原 函数

3.context.fn = this

这里this指向原函数,context就是我们调用我们mycall()方法需要绑定this的那个对象,给他添加个fn属性,将原函数赋值给fn属性.

4.let args = [...arguments].slice(1)

知识点哈!(...) ES6中新增语法,为扩展运算符,它在函数构或数组构造时将数组子项在语法层面展开但是 它不适合多层嵌套的数据和对象.通过slice()方法将myCall()方法中除了第一个的其余参数取出,赋值给args.此时 this指向还是原函数.

5.let r = context.fn(args)

这里实际就是运行函数,将结果运行结果保存到r上,区别就是这个运行不是原函数运行的,是我们需要绑 定的那个对象运行的函数,此时this指向就是需要绑定的那个对象了,因为是它运行的函数,所以自然this就 指向它了

6.delete context.fn

将fn属性删除

7.return r

返回函数运行结果,此时this的指向就成功的修改了.

bind()

什么是bind()?

**bind()** 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用。

我们可以看下面的代码理解下

var a = {
    b:18,
    c: function (){
        return this.b
    }
}
var x = a.c
console.log(x())  //输出结果undefined
var y = x.bind(a)
console.log(y())  //输出结果18
//当函数体赋值给x运行时,此时调用的this指向的时window,但是通过bind将this指向为对象a,所以自然就能访问到变量b

运行bind函数时会创建一个新的函数,它是原函数的拷贝,并且拥有执行的this和参数.

以上是关于自己学习理解的内容.有错误的地方肯请各位指出.