函数调用面试题回顾
var obj = {
foo:function(){
console.log(this)
}
}
var bar =obj.foo
obj.foo() //打印出的this是obj
bar() //打印出的this是window
window.n = 'window name'
let obj = {
n: 'obj name',
sayN(){
console.log(this.n)
}
}
let fn = obj.sayN
fn() // window name
window.n = 'window name'
let obj = {
n: 'obj name',
sayN: () => {
console.log(this.n)
}
}
obj.sayN() // window name
有没有主体,有:obj;注意看是否是箭头函数,此时sayN的this指向的是obj,因此箭头函数this指向外围:window
function fo (i) {
console.log('fo', i)
console.log(this === window) // true
this.count++
}
fo.count = 0
for (var i = 0; i < 5; i++) {
fo(i)
}
console.log(fo.count, count) // 0, NaN
函数执行fo(),前面没有主体,因此this指向window,window.count为NaN,因为window.count没有初始化
老师的理解
func(p1, p2)
obj.child.method(p1, p2)
第一道第一种
obj.child.method(p1, p2) 等价于
obj.child.method.call(obj.child, p1, p2)
第二道
func(p1, p2) 等价于
func.call(undefined, p1, p2)
如果你传的 context 是 null 或 undefined,那么 window 对象就是默认的 context,因此上面的打印结果是 window
如果你希望这里的 this 不是 window,很简单:
func.call(obj) // 那么里面的 this 就是 obj 对象了
我的理解
两种形式,首先看函数名前面有没有主体,接着看是否是箭头函数
func(p1, p2)
obj.child.method(p1, p2)
[ ] 语法
function fn (){ console.log(this) }
var arr = [fn, fn2]
arr[0]() // 这里面的 this 又是什么呢?
相当于arr.0() —> 无非两种,看函数名前是否有主体
与转换代码里的 obj.child.method(p1, p2) 对应上
所以里面的 this 就是 arr 了
箭头函数
fn = () =>{}
this =>箭头函数名所在this 的 外面this
箭头函数里并没有 this,如果你在箭头函数里看到 this,你直接把它当作函数名所在this 的 外面this即可
要注意立即执行函数和setTimeout函数
window.n = 'window name'
let obj = {
n: 'obj name',
sayN: () => {
console.log(this.n)
}
}
obj.sayN() // window name
此处sayN不是箭头函数则this指向obj,现在指向obj的外部,因此是window
var name = 'global'
var obj = {
name: 'obj',
test: function () {
// 这里的this指向obj
(() => {
// 注意这里的是箭头函数
var name = '2'
console.log(this.name)
})()
}
}
obj.test() // obj
首先看函数名前面有没有主体:obj,接着看是否是箭头函数,可以确定的是test{}里的this是obj,最后看箭头函数的外围
var name ='111'
obj ={
name:'abc',
fn:function(){
setTimeout(()=>{
console.log(this.name)
},0)
}
}
obj.fn()
//abc
var name ='111'
obj ={
name:'abc',
fn:function(){
setTimeout(function(){
//function 匿名函数,函数名所在的this就在()中,里面没有,因此指向window
console.log(this.name)
},0)
}
}
obj.fn()
//111
一题详解
function foo () {
return () => {
console.log(this.name)
}
}
var obj1 = {
name: 'obj1'
}
var obj2 = {
name: 'obj2'
}
var temp = foo.call(obj1)
temp.call(obj2) // obj1
相当于
function foo () {
return (() => {
console.log(this.name)
})()
}
var obj1 = {
name: 'obj1'
}
var obj2 = {
name: 'obj2'
}
foo.call(obj1) //obj1
foo()执行,this指向obj1,通过立即执行函数获得外围this,因此打印obj1。上图输入temp.call(obj2),也就是temp(),在箭头函数那this指向obj2,在箭头函数里this指向obj2的外围
foo = ()=>{
console.log(this.name)
}
var obj1 = {
name: 'obj1'
}
var obj2 = {
name: 'obj2'
}
foo.call(obj1) //global
function foo(){
console.log(this.name)
}
var obj1 = {
name: 'obj1'
}
var obj2 = {
name: 'obj2'
}
foo.call(obj1) //obj1
new X
new Fn()
this =》新的对象
如果函数是通过new调用(new绑定), 那么this指向新创建的对象
- 创建一个全新的对象
- 该新对象关联到大X原型, 把该对象绑定到大X this
- 执行函数中代码
- 如果没有其他返回, 默认返回该新对象(自动return this)
function Person () {
this.name = '2'
}
console.log(new Person().name) // 2
class A{
constructor(){
this.name = 'A'
}
sayName(){
console.log(this.name)
}
}
class B extends A{
constructor(){
super()
this.name = 'B'
}
}
let obj = new B()
console.log(obj.sayName()) //B
函数前面有主体obj,obj this指向B
function test (thing) {
this.thing = thing
}
var obj1 = {
test: test
}
var obj2 = {}
// 隐式绑定
obj1.test(2)
console.log(obj1.thing) // 2
// 显示绑定
obj1.test.call(obj2, 3)
console.log(obj2.thing) // 3
// 可见new绑定优先级高于隐式绑定, 如果不是的化 test.thing=2
var test = new obj1.test(4)
console.log(obj1.thing) // 2
console.log(test.thing) // 4
文章参考链接
一文搞懂this关键字
https://zhuanlan.zhihu.com/p/84944648
this 的值到底是什么?一次说清楚
https://zhuanlan.zhihu.com/p/23804247
你怎么还没搞懂 this?
https://zhuanlan.zhihu.com/p/25991271