call、bind、apply三者的区别
当一个函数作为构造器使用时(通过 new 关键字), 它的 this 值绑定到新创建的那个对象。3、如果你在声明一个变量的时候没有使用var或者let、const(es6),你就是在给全局的this添加或者改变属性值。this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined。对于函数中的this的指向问题,有一句话很好用:运行时this永远指向最后
·
一、 三者区别
- call、bind、apply 都是 JavaScript 中用于改变函数执行上下文(即 this 指向)的方法。
- call 和 apply 的作用是一样的,都是用来调用函数并且改变函数内部的 this 指向。区别在于传参的方式不同,call 的参数是一个一个传递的,而 apply 的参数是以数组的形式传递的。
- bind 方法不会立即执行函数,而是返回一个新的函数,这个新的函数的 this 值被绑定到了指定的对象,调用时也可以传入参数。同时使用 bind 方法可以实现柯里化,即将函数转化为接收部分参数的函数。
call | apply | bind |
---|---|---|
是函数的标准调用 | 也是函数的标准调用 | 可以改变函数this指向,先改变函数this指向,然后再去调用函数,才可以执行 |
可以强制改变this指向 | 也可以将this改变任意一个东西 | 改变this指向的特点是不会立刻执行 |
可以将this改变成任意的一个东西 | 传递参数的时候必须是一个数组 | 使用与改变事件中的this指向 为什么?它不会立刻执行,可以让用户触发以后在执行 |
可以改变事件中的this指向 事件就直接执行了 | 也可以改变方法中的this指向 | |
还可以改变方法中的this指向 | 不可以改变箭头函数的this指向 |
call
- fn.call
当前实例(函数fn)通过原型链的查找机制,找到function.prototype上的call方法,function call(){[native code]} - fn.call()
把找到的call方法执行
当call方法执行的时候,内部处理了一些事情
1.首先把要操作的函数中的this关键字变为call方法第一个传递的实参
2.把call方法第二个及之后的实参获取到
3.把要操作的函数执行,并且把第二个以后传递进来的实参传递给函数
fn.call([this],[param]...)
- call中的细节
1.非严格模式
如果不传参数,或者第一个参数是null或nudefined,this都指向window
let fn = function(a,b){
console.log(this,a,b);
}
let obj = {name:"obj"};
fn.call(obj,1,2); // this:obj a:1 b:2
fn.call(1,2); // this:1 a:2 b:undefined
fn.call(); // this:window a:undefined b:undefined
fn.call(null); // this=window a=undefined b=undefined
fn.call(undefined); // this=window a=undefined b=undefined
2.严格模式
第一个参数是谁,this就指向谁,包括null和undefined,如果不传参数this就是undefine
apply
- apply:和call基本上一致,唯一区别在于传参方式
apply把需要传递给fn的参数放到一个数组(或者类数组)中传递进去,虽然写的是一个数组,但是也相当于给fn一个个的传递
fn.call(obj, 1, 2);
fn.apply(obj, [1, 2]);
bind
- bind:语法和call一模一样,区别在于立即执行还是等待执行,bind不兼容IE6~8
fn.call(obj, 1, 2); // 改变fn中的this,并且把fn立即执行
fn.bind(obj, 1, 2); // 改变fn中的this,fn并不执行
this改变为obj了,但是绑定的时候立即执行,当触发点击事件的时候执行的是fn的返回值undefined
document.onclick = fn.call(obj);
bind会把fn中的this预处理为obj,此时fn没有执行,当点击的时候才会把fn执行
document.onclick = fn.bind(obj);
二、this指向与三者的关系
- 在浏览器里,在全局范围内this 指向window对象;
- 在函数中,this永远指向最后调用他的那个对象;
- 构造函数中,this指向new出来的那个新的对象;
- call、apply、bind中的this被强绑定在指定的那个对象上;
- 箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;
- apply、call、bind都是js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参
三、全局中的this:
在浏览器里,在全局范围内:
1、this等价于window对象;
2、用var声明一个变量和给this或者window添加属性是等价的;
3、如果你在声明一个变量的时候没有使用var或者let、const(es6),你就是在给全局的this添加或者改变属性值。
// 1
console.log(this === window); //true
//2
var name = "Jake";
console.log(this.name ); // "Jake"
console.log(window.name ); // "Jake"
//3
age = 23;
function testThis() {
age = 18;
}
console.log(this.age ); // 23
testThis();
console.log(this.age ); // 18
四、函数中的this:
对于函数中的this的指向问题,有一句话很好用:运行时this永远指向最后调用它的那个对象。
var name = "windowsName";
function sayName() {
var name = "Jake";
console.log(this.name); // windowsName
console.log(this); // Window
}
sayName();
console.log(this) // Window
------------------------------------------------------------------------------
function foo() {
console.log( this.age );
}
var obj1 = {
age : 23,
foo: foo
};
var obj2 = {
age : 18,
obj1: obj1
};
obj2.obj1.foo(); // 23
五、构造函数中的this:
所谓构造函数,就是通过这个函数生成一个新对象(object)。当一个函数作为构造器使用时(通过 new 关键字), 它的 this 值绑定到新创建的那个对象。如果没使用 new 关键字, 那么他就只是一个普通的函数, this 将指向 window 对象。
更多推荐
已为社区贡献1条内容
所有评论(0)