侧边栏壁纸
博主头像
@小佑前端

学而不厌 不耻下问

  • 累计撰写 63 篇文章
  • 累计创建 83 个标签
  • 累计收到 12 条评论

目 录CONTENT

文章目录

JavaScriptThis指向问题

@小佑前端
2021-02-04 / 0 评论 / 0 点赞 / 437 阅读 / 1,166 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2022-10-12,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。
  • 在全局作用域下this的指向就是window,
let a = 10
console.log(this.a) // 不管是非严格模式还是严格模式都是this
  • 函数执行的时候,看前面有没有.如果有点.前面是谁,函数执行的时候,里面的this就是谁,如果没有点.里面的this就是window(非严格模式下),在严格模式下就是undefined
let obj ={
	name:10
}
function fn(){
	console.log(this) 
}
obj.fn() // this输出的是obj
  • 给元素绑定事件的时候,当事件触发里面的this就是当前绑定的元素
<div id=ele> ele </div>

let ele.onclick = function(){
	console.log(this) // 则是被绑定的元素
}
  • 自执行函数的this非严格模式下window,在严格模式下就是undefined
(function(){
	console.log(this)
})()
  • 回调函数里面this是window
function fn(callback){
	console.log(this)
	callback()
}
fn(function(){
	console.log(this)
})
  • 通过类创造的实例,构造函数中的this指的就是当前的实例
function fn(){
	this.name = "lili",
	this.age = 20
}
var f1 = new fn() //  当前的this就是f1的实例
var f2 = new fn() //  当前的this就是f2的实例

通过call/apply/bind可以更改this的指向

call

function fn(){
	console.log(this)
}
let obj = {
	name:"lili"
}
fn.call(obj) // 此时this就被指向obj
  • 构造函数里面的this就是指向当前的实例,通过this添加的属性名和都属性值都是跟当前的实例添加的
Function.prototype.MyCall = function MyCall(context, ...params) {
     /*
    思路: 给CONTEXT设置一个属性(例如:xxx,新增的属性不要和原始CONTEXT中的属性冲突(设置Symbol唯一值属性)),
    让属性值等于要执行的函数(即:this(fn)),
    后面就可以基于CONTEXT.XXX()执行,这样即可以把函数执行了,也让函数中的this改为CONTEXT了....
    注意:给原始值加属性不会报错但是也获取不到,保证CONTEXT不是原始值类型
    */
    // 为了过滤出传入参数是基本类型的情况
    if (context === null) context = window;
    if (!/^(object|function)$/.test(typeof context)) context = Object.apply(context)

    let _this = this,
            key = Symbol('KEY'),  //  利用Es6新增属性Symbol生成一个唯一的属性名
            result;
     
    // 给参数中新增个uniqueKey属性与调用的函数关联
    context[key] = _this;
    
    // 新增完要移除
    result = context[key](...params) 
    
    // 可以使用Es6新增的API移除对象里面的属性
    Reflect.deleteProperty(context, key) 
    
    // 把函数执行的结果 return 出去
    return result
}

call和apply各自的定义:

  • apply:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.apply(A, arguments);即A对象应用B对象的方法。

  • call:调用一个对象的一个方法,用另一个对象替换当前对象。例如:B.call(A, args1,args2);即A对象调用B对象的方法。

call和apply共同之处:

  • 都可以用来代替另一个对象调用一个方法,将一个函数的对象上下文从初始的上下文改变为由thisObj指定的新对象”。

call和apply不同之处:

  • apply:最多只能有两个参数——新this对象和一个数组argArray。如果给该方法传递多个参数,则把参数都写进这个数组里面,当然,即使只有一个参数,也要写进数组里。如果argArray不是一个有效的数组或arguments对象,那么将导致一个TypeError。如果没有提供argArray和thisObj任何一个参数,那么Global对象将被用作thisObj,并且无法被传递任何参数。

  • call:它可以接受多个参数,第一个参数与apply一样,后面则是一串参数列表。这个方法主要用在js对象各方法相互调用的时候,使当前this实例指针保持一致,或者在特殊情况下需要改变this指针。如果没有提供thisObj参数,那么 Global 对象被用作thisObj。

实际上,apply和call的功能是一样的,只是传入的参数列表形式不同。

bind

function MyBind(context,...params){
	let _this = this;
	return function proxy(...args){
		params = params.concat(agrs);
		return _this.call(context,...params)
	}
}
  • bind和call/apply的最大区别就是他不是立即执行而call/apply它时立即就执行了
  • bind可以用于点击事件,触发点击事件后才会执行。

最后声明一下:箭头函数中没有this,也没有arguments,但是在箭头函数中用this,会向上级作用域链去找

0

评论区