抱歉,您的浏览器无法访问本站

本页面需要浏览器支持(启用)JavaScript


了解详情 >

Mr.wang

Time flies and people come and go

js函数中的this指向及call apply bind对于this的改变

如何理解This指向

this :谁调用它 他就指向谁。(this 永远指向最后调用它的那个对象

1.在浏览器:如果this是在函数外部则this指向window

2.在node环境:如果this在函数外部则指向{}

​ 如果有new绑定 则指向这个new的实例对象

​ 函数是否通过 call,apply 调用,或者使用了 bind 绑定,如果是,那么this绑定的就是指定的对象【归结为显式绑定】。

这里同样需要注意一种特殊情况,如果 call,apply 或者 bind 传入的第一个参数值是 undefined 或者 null,严格模式下 this 的值为传入的值 null /undefined。非严格模式下,实际应用的默认绑定规则,this 指向全局对象(node环境为global,浏览器环境为window)

隐式绑定,函数的调用是在某个对象上触发的,即调用位置上存在上下文对象。典型的隐式调用为: xxx.fn()

箭头函数的情况:箭头函数没有自己的this,继承外层上下文绑定的this。

看看具体例子

1
2
3
4
5
6
7
8
var name = "windowsName";
var a = {
// name: "Cherry",
fn : function () {
console.log(this.name); //==》undefined
}
}
window.a.fn();

说明:这里有通过window调用a ,最后调用的是谁的呢?? 其实是a最后调用了this=》》a里面没有那么这个属性,即使外面的window有name也不会调用==》》就像我们对于变量的调用一样,,函数内部的变量不可以使用其他的函数内部的变量,a和window是两个函数 即使window包括a但是调用的时候是使用this 指向了a 也就是标明 我一定要使用a里面的属性

再看看这个坑

1
2
3
4
5
6
7
8
9
10
var name = "windowsName";
var a = {
name : null,
// name: "Cherry",
fn : function () {
console.log(this.name); //==> windowsName
}
}
var f = a.fn;
f();

为什么和之前的调用差不多 this却是指向window 由上往下看,var f 的时候根本没有调用a.fn;

最后fn() 是使用了window调用的 所以指向了外面的name

this 的指向并不是在创建的时候就可以确定的 永远指向最后调用的它

call和apply以及bind都与this有关 因为他们改变了this的指向

this指向改变的几种方法

1.当你new一个对象时 this就指向创建的实例
1
2
let date = new Date()
// 我们可以使用data创建时间 这是因为data的this在赋值当中已经指向实例new Date()
1
2
3
4
5
new 的实现原理:
创建一个空对象,构造函数中的this指向这个空对象
这个新对象被执行 [[原型]] 连接
执行构造函数方法,属性和方法被添加到this引用的对象中
如果构造函数中没有返回其它对象,那么返回this,即创建的这个的新对象,否则,返回构造函数中返回的对象。
2.使用闭包解决,有两层函数可以再第一层使用_this= this改变指向
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//在这里使用的是闭包的原理 也可以改变this的指向
function(){
let _this = this
function(){
console.log(_this)
}
}
//可执行
function fn() {
let _this = this
return function () {
console.log(_this)
}()
}
fn()
3.es6的箭头函数 指向外部的this,()=>{}

箭头函数的 this 始终指向函数定义时的 this,而非执行时。

call apply bind

call

1
2
3
4
5
6
7
8
9
10
11
12
let Object = {
name: 'Mr.wang',
first() {
console.log(this.name)
},
second() {
setTimeout(function () {
console.log(this.name);
}.call(Object));
}
}
Object.second() //==> 输出为 Mr.wang

apply

1
2
3
4
5
6
7
8
9
10
11
12
let Object = {
name: 'Mr.wang',
first() {
console.log(this.name)
},
second() {
setTimeout(function () {
console.log(this.name);
}.apply(Object));
}
}
Object.second() //==> 输出为 Mr.wang

bind

1
2
3
4
5
6
7
8
9
10
11
12
let Object = {
name: 'Mr.wang',
first() {
console.log(this.name)
},
second() {
setTimeout(function () {
console.log(this.name);
}.bind(Object));
}
}
Object.second() //==> 输出为 Mr.wang

apply 和 call 的区别

他们之间的区别只是传入参数的区别

appll(this,[a,b,c])

call(this,a,b,c)

bind与apply和call有着大的区别

bind会生成新的函数,需要调用再次调用

setTimeout会自动调用

评论