Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

tokobin 3点半到五点半 2小时速肝this指向问题 #62

Open
0xtokobin opened this issue Jun 15, 2023 · 0 comments
Open

tokobin 3点半到五点半 2小时速肝this指向问题 #62

0xtokobin opened this issue Jun 15, 2023 · 0 comments
Assignees
Labels

Comments

@0xtokobin
Copy link
Collaborator

0xtokobin commented Jun 15, 2023

https://juejin.cn/post/6844904083707396109#heading-8

个人总结:
第一就是默认绑定 默认指向window 严格模式指向undefined
第二 隐式绑定 指向最后调用的对象 注意联系上下文

隐式绑定的隐式丢失问题

其实就把之前的赋值给一个变量 然后使用变量 改不了之前隐式绑定的规则 指向最后调用他的那个对象 这样子使用变量就会把this的指向给改变

把函数当做参数传入也是一样的本质 就是最后调用的对象被改变 然后this就变了
function foo () {

console.log(this.a)

}
function doFoo (fn) {

console.log(this)

fn()

}
var obj = { a: 1, foo }

var a = 2

doFoo(obj.foo)

///

function foo () {

console.log(this.a)

}

function doFoo (fn) {

console.log(this)

fn()

}

var obj = { a: 1, foo }

var a = 2

var obj2 = { a: 3, doFoo }

obj2.doFoo(obj.foo)

很明显第一个this 指向obj2 而第二个this没有明确的最后调用对象 直接指向window就完事了ok? 简简单单

显式绑定 :就是apply bind call 去改变this的指向

通过call()、apply()或者bind()方法直接指定this的绑定对象, 如foo.call(obj)。

这里有几个知识点需要注意:

使用.call()或者.apply()的函数是会直接执行的
bind()是创建一个新的函数,需要手动调用才会执行
.call()和.apply()用法基本类似,不过call接收若干个参数,而apply接收的是一个数组。 切记bind是创建一个新的函数要调用他。

看下面经典面试题:
function foo () {

console.log(this.a)

}

var obj = { a: 1 }

var a = 2

foo()

foo.call(obj)

foo().call(obj)

在这段代码中,this的指向取决于函数foo如何被调用。

foo(): 在非严格模式下,如果一个函数独立调用(即它不是对象的方法或者通过 new 关键字调用),那么 this 通常指向全局对象,即在浏览器中的 window。因此,这里 this.a 将会输出 2。如果在严格模式下(通过 'use strict' 指定),this 将会是 undefined。

foo.call(obj): 使用 call 方法,我们可以指定函数内部 this 的指向。在这里,this 会指向我们作为参数传入的 obj 对象,所以 this.a 输出 1。

foo().call(obj): 这里会抛出一个错误。原因是 foo() 这个表达式会先被求值,也就是执行 foo 函数。foo 函数返回 undefined(因为没有指定返回值),然后我们试图在 undefined 上调用 call 方法,这会导致一个类型错误。因此,foo().call(obj) 会抛出错误。

var obj = {
a: 1,
foo: function (b) {
b = b || this.a
return function (c) {
console.log(this.a + b + c)
}
}
}
var a = 2
var obj2 = { a: 3 }

obj.foo(a).call(obj2, 1)
obj.foo.call(obj2)(1)
这道题小骚 想了5分钟起码 a出来了 6,6

总结:this 永远指向最后调用它的那个对象
匿名函数的this永远指向window
使用.call()或者.apply()的函数是会直接执行的
bind()是创建一个新的函数,需要手动调用才会执行
如果call、apply、bind接收到的第一个参数是空或者null、undefined的话,则会忽略这个参数
forEach、map、filter函数的第二个参数也是能显式绑定this的

new 绑定:

使用new来调用一个函数,会构造一个新对象并把这个新对象绑定到调用函数中的this。

function Person (name) {
this.name = name
this.foo1 = function () {
console.log(this.name)
}
this.foo2 = function () {
return function () {
console.log(this.name)
}
}
}
var person1 = new Person('person1')
person1.foo1()
person1.foo2()()
输出 总结就是new 的话 person1 直接变成this 也就是被赋值的那个变成this
person1
undefined

箭头函数绑定:

在箭头函数中,this被设置为它被创建时的上下文 所以直接好用

var name = 'window'
function Person (name) {
this.name = name
this.foo1 = function () {
console.log(this.name)
}
this.foo2 = () => {
console.log(this.name)
}
}
var person2 = {
name: 'person2',
foo2: () => {
console.log(this.name)
}
}
var person1 = new Person('person1')
person1.foo1()
person1.foo2()
person2.foo2()

a出来 person1 person1 windows 局部作用域 函数体内 对象不算 所以直接指向window

综合题和手写下次复习再撸吧

@0xtokobin 0xtokobin added the es6 label Jun 15, 2023
@0xtokobin 0xtokobin self-assigned this Jun 15, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant