下列函数中 this 的指向 :
let obj = {
name:'张三',
age:18,
sayHi(){
let fn1 = function(){
console.log(this)
}
fn1()
let fn2 = ()=>{
console.log(this)
}
fn2()
},
eat:()=>{
let fn3 = function(){
console.log(this)
}
fn3()
let fn4 = ()=>{
console.log(this)
}
fn4()
}
}
obj.sayHi()
obj.eat()
解题辅助知识点
1 . 作用域
变量作用域 : 变量起作用的范围
- 全局作用域(全局变量) :在函数外外面声明,页面任何地方都可以使用
- 局部作用域(局部变量) : 在函数内部声明,只能在函数内部使用
- 块级作用域 : 在大括号里面声明的变量(分支和循环),只能在大括号内部使用
//1.全局变量 : 全局作用域
let num = 10
function fn () {//函数的形参相当于在函数内部声明变量 : 局部变量
//2.局部变量: 局部作用域(函数内部作用域)
let age = 30
console.log(age)
}
fn()
for (let i = 1; i <= 10; i++) {
//3.块级变量:块级作用域(只能在大括号内部使用)
console.log(i)
}
2 . 作用域链
原理 : 默认情况下,js代码处于全局作用域(0级),当我们声明一个函数的时候,就会开辟一个局部作用域. 函数里面也可以声明函数,就会又形成局部作用域(2级),以此类推就会形成作用域链
//全局作用域(0级)
let num = 10
function fn () {
//局部作用域(1级)
let num = 20
console.log('1级作用域' + num)//20
function fn1 () {
//局部作用域(2级)
let num = 30
console.log('2级作用域' + num)//30
}
fn1()
}
fn()
console.log('0级作用域' + num)//10
变量在作用域链中的访问规则:就近原则
- 当你在某个作用域访问变量的时候,会先看当前作用域有没有声明。如果有则访问当前作用域的变量。没有就找上级,上级也没有就继续往上。直到作用域最顶端(0级),如果0级也没有,则程序会报错。 xxx is not defined
3 . 函数中的this指向
function函数this指向: 谁‘调用’我,我就指向谁 (取决于调用,与声明无关)
- 普通函数 :
函数名() this 指向 window - 对象方法 :
对象名.方法名() this 指向对象 - 构造函数 :
new 函数名() this 指向 new 创建的实例对象
箭头函数中的this : 谁‘声明’我,我就指向谁
- 真正的含义 : 箭头函数没有this
- 箭头函数本身是没有this的,本质是通过作用域链,访问上一级的this
//0级作用域链
//1.普通函数
let fn = () => {
//1级作用域链
console.log(this)
}
fn() //window
//2.对象的方法
let obj = {
name: '张三',
age: 20,
eat () {//function(){}
//1级作用域链
console.log(this)//obj
let fn = () => {
//2级作用域链
console.log(this)//obj
}
fn()
},
learn: () => {
//1级作用域链 : this访问0级
console.log(this)//window
}
}
obj.eat() //obj function函数的this取决于调用
obj.learn() //window 箭头函数跟调用没关系,永远都是访问上级作用域this
解题思路
- sayHi() 是对象的方法, 在1级作用域链, this 指向 obj
- f1() 在2级作用域链, 但是 function 函数取决于调用, fn1()这是普通函数调用, this 指向 window
- fn2 = ()=>{} 在2级作用域链, 箭头函数访问上级作用域也就是 sayHi() , this 指向 obj
- eat:()=>{} 在1级作用域链,但是尖头函数访问上一级作用域0级, this 指向 window
- fn3 = function(){} 在2级作用域链, function 函数取决于调用, fn3()这是普通函数调用, this 指向 window
- fn4 = ()=>{} 在2级作用域链, 箭头函数访问上级作用域也就是 eat:()=>{} , this 指向 window
let obj = {
name:'张三',
age:18,
sayHi(){
//1级链 this: obj
let fn1 = function(){
//2级链 ; function函数取决于调用 fn1()这是普通函数调用
console.log(this)//window
}
fn1()
let fn2 = ()=>{
//2级链 : 箭头函数访问上级 1级this -> obj
console.log(this)//obj
}
fn2()
},
eat:()=>{
//1级链 this:window
let fn3 = function(){
//2级链 function函数取决于调用 fn3()这是普通函数调用
console.log(this)//window
}
fn3()
let fn4 = ()=>{
//2级链: 箭头函数访问上级 1级this -> window
console.log(this)//window
}
fn4()
}
}
obj.sayHi()
obj.eat()
答案 :
f1 : window
f2 : obj
f3 : window
f4 : window
|