this解析

this解析

在这里插入图片描述

  • 当函数被正常调用时,在严格模式下,this 值是 undefined,非严格模式下 this 指向的是全局对象 window;

  • 通过一个对象来调用其内部的一个方法,该方法的执行上下文中的 this 指向对象本身

  • ES6 中的箭头函数并不会创建其自身的执行上下文,所以箭头函数中的 this 取决于它的外部函数

  • new 关键字构建好了一个新对象,并且构造函数中的 this 其实就是新对象本身

    • 当执行 new CreateObj() 的时候,JavaScript 引擎做了如下四件事:
      • 首先创建了一个空对象 tempObj;
      • 接着调用 CreateObj.call 方法,并将 tempObj 作为 call 方法的参数,这样当 CreateObj 的执行上下文创建时,它的 this 就指向了 tempObj 对象;
      • 然后执行 CreateObj 函数,此时的 CreateObj 函数执行上下文中的 this 指向了 tempObj 对象;
      • 最后返回 tempObj 对象。
  • 嵌套函数中的 this 不会继承外层函数的 this 值。

1. 全局环境下的this

1. 在非严格模式下,this指向window,在通过use strict指明严格模式的情况下指向undefined。
2. 给元素的某个事件绑定方法,当事件触发方法执行的时候,方法中的this是当前操作元素本身。
3. 当方法执行的时候,我们看方法前面是否有点,没有点this是window或undefined(严格模式下),有点,前面的this就是谁。

var name = 'zzf';
function fn() {
    console.log(this.name)
}
var obj = {
    name : 'zdf',
    fn:fn
}
obj.fn();  // this:obj
fn() //this: window
var fullName = 'language';
var obj = {
    fullname: 'javascript',
    prop: {
        getFullName: function() {
            return this.fullName;
        }
    }
}
console.log(obj.prop.getFullName()); 
// obj.prop.fullName => undefined
var test = obj.prop.getFullName;
console.log(test());
// window.fullName = 'language'

再来看一道高阶题目

var name = 'window';
var Tom = {
    name: 'Tom',
    show: function (){
        console.log(this.name);
    }
    wait: function(){
        // this:Tom  Tom.show()
        var fun = this.show;
        fun(); // this:window => this.name = 'window'
    }
}
Tom.wait();

Tom调用wait()方法,this指向Tom, 但是在wait()方法内,谁调用了fun()?虽然fun赋值给this.show,但是调用fun()的是window,结果输出window.name也就是’window’。

const o1 = {
	text: 'o1',
	fn: function() {
		return this.text
	}
}
const o2 = {
	text: 'o2',
	fn: function() {
		return o1.fn()
	}
}
const o3 = {
	text: 'o3',
	fn: function() {
		var fn = o1.fn
		return fn()
	}
}
console.log(o1.fn()) // 'o1'
console.log(o2.fn()) // 'o1'
console.log(o3.fn()) // undefined

和上面的类似,o3.fn() 最终盗用fn()的是window,window没有text,结果为undefined。

2. call/bind/apply

这里是面试的高频点,甚至会手写这3个方法。
call/bind/apply都是用来改变相关函数this指向的,但是call和apply直接进行函数调用,bind不会执行相关函数,而是返回新的函数,新的函数已经绑定了新的this指向,开发者可以手动调用它。call和apply的区别在于参数上的设定。

const target = {}
fn.call(target, 'arg1','arg2')
fn.apply(target, ['arg1', 'arg2']
fn.bind(target, 'arg1', 'arg2')()
window.val = 1;
var json = {
    val: 10;
    dbl: function() {
        this.val *= 2;
    }
}
json.dbl();// json.val = 20
dbl(); // window.val = 2;
json.dbl.call(window); // window.val = 4;

3. 构造函数

在构造函数模式执行中,函数体中的this是当前类的实例。
这引出一个很重要的面试题:new操作符调用构造函数时具体做了什么?(手写new操作符)

  • 创建一个新的对象
  • this指向新的对象
  • 为对象添加属性和方法等
  • 返回新的对象

注意:在构造函数中,我们可以显式的return一个值,如果return的是一个基本类型,对返回的实例没有影响,如果手动return的是一个引用类型的值,会把默认返回的实例给替换掉(所以在构造函数模式执行下,我们一般都不要手动写return,防止把返回的实例给替换掉)

4. 箭头函数

箭头函数没有的this,this的指向是由外层作用域来决定的。

const foo = {
	fn: function() {
		setTimeout(function() {
			console.log(this) // window
		})
	}
}

const foo = {
  fn: function() {
    setTimeout(() => {
      console.log(this)
    })
  }
}
console.log(foo.fn()) // {fn:f}

5. this的优先级

显式绑定:call / apply/ bind/ new等对this进行绑定
隐式绑定:根据调用关系确定

call、bind的显示绑定一般优先级更高,不然也无法更改this指向不是。
new绑定的优先级比显式bind的绑定的更高。
箭头函数的绑定无法修改。

var a = 1
const foo = () => a => {
  console.log(this.a)
}

const obj1 = {
  a: 2
}

const obj2 = {
  a: 3
}
var bar = foo.call(obj1)
console.log(bar.call(obj2)) // 1
let a = 1
const foo = () => a => {
  console.log(this.a)
}

const obj1 = {
  a: 2
}

const obj2 = {
  a: 3
}
var bar = foo.call(obj1)
console.log(bar.call(obj2)) // undefined
// 想一想这里为什么是undefined?

6. 实现一个bind

这部分会写一个手写专题,尽请期待。

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值