Javascript详解-明确this

JS中的this:

绝大多数情况下,函数的调用方式决定了this的值(运行时绑定)。this不能再执行期间被赋值,并且在函数被调用时this的值也可能会不同!

如何判断this中的值:

非严格模式-->一个对象 , 严格模式-->任意值

1.全局执行环境中,指向全局对象(非严/严格模式)

2.函数内部,取决于被调用方式

        2.1直接调用的this值:

                2.1.1 非严格模式: 全局对象(window)

                2.1.2 严格模式: undefined

        2.2 对象方法调用的this值:

                2.2.1 调用者

tips:

1.'use strict' 为整个脚本开启严格模式

2.为函数开启严格模式

function func(){
'use strict'
}

3.无论上述那种情况,严格模式的开启都应置顶(注释除外) !!


如何指定this中的值:

1. 调用时指定:

        1.1 call方法

        依次传入参数 func.call(XXX,1,2)

        1.2 applay方法

        按数组传入参数 func.apply(XXX,[1,2])

2.创建时指定

        2.1 bind方法

        2.2 箭头函数

备注:

 1、这个函数几乎与 apply() 相同,只是函数的参数以列表的形式逐个传递给 call(),而在 apply() 中它们被组合在一个对象中,通常是一个数组——例如,func.call(this, "eat", "bananas") 与 func.apply(this, ["eat", "bananas"])

2、所有函数都是Function的实例对象。

手写call、apply、bind:

call:Function 实例的 call() 方法会以给定的 this 值和逐个提供的参数调用该函数。
        // 1、定义myCall方法
        // 3、接收剩余参数并返回结果
        // ...args 表示参数不固定的剩余参数 是一个数组
        Function.prototype.myCall = function(thisArg,...args){
        // 2、设置this并调用原函数
        // thisArg 传入的设置为this的对象
        // this 原函数(原函数.myCall)
           thisArg.f = this
        // 调用赋值后函数,使用...args打开/展开数组
           const res = thisArg.f(...args)
        // 删除动态生成的属性
            delete thisArg.f
            console.log(args)
            return res
        }
        // 执行代码
        const person = {
            name: 'ian'
        }
        function func(numA,numB){
            console.log(this)
            console.log(numA,numB)
            return numA + numB
        }
        // 测试myCall的可复用性
        function funM(numA,numB,numC){
            console.log(this)
            return numA*numB*numC
        }
        const res = func.myCall(person,2,8)
        console.log('返回值1为:',res)
        console.log('返回值2为:',funM.myCall(person,1,2,3))

测试手写的mycall的复用性

        我们在上述代码中针对动态生成属性(方法)没有很好的处理,只是鲁莽的将其删除,而忽视可能存在f,为bug埋下隐患,为此我们将使用Symbol函数提供类似(OID)的方法来有效保护属性(方法)和删除动态生成的(方法)。

        如下图可见,Symbol函数可以提供完全不同的标记。

将代码进行优化:

        Function.prototype.myCall = function(thisArg,...args){
        // 使用Symbol创建一个唯一的属性名
        const key = Symbol()
        // 将原函数赋值给thisArg对象的属性
        thisArg[key] = this
        // 调用赋值后函数,使用...args打开/展开数组
        const res = thisArg[key](...args)
        // 删除动态生成的属性
        delete thisArg[key]
        return res
        
apply:Function 实例的 apply() 方法会以给定的 this 值和作为数组(或类数组对象)提供的 arguments 调用该函数。

同理可得:

        Function.prototype.myApply = function(thisArg,args){
            const key = Symbol()
            thisArg[key] = this
            const res = thisArg[key](...args)
            delete thisArg[key]

            return res
        }
        // 执行代码
        const person = {
            name: 'ian'
        }
        function func(numA,numB){
            console.log(this)
            console.log(numA,numB)
            return numA + numB
        }
        const res = func.myApply(person,[2,8])
        console.log('返回值1为:',res)

bind:Function 实例的 bind() 方法创建一个新函数,当调用该新函数时,它会调用原始函数并将其 this 关键字设置为给定的值,同时,还可以传入一系列指定的参数,这些参数会插入到调用新函数时传入的参数的前面。
 // 1.定义myBind方法
        Function.prototype.myBind = function(thisArg,...args){
            // 返回一个函数
            return (...reArgs) => {
                // 调用原函数并返回结果
                return this.call(thisArg,...args,...reArgs)
            }
        }
        function func (numA,numB,numC,numD){
            console.log(this)
            console.log(numA,numB,numC,numD)
            return numA + numB + numC + numD
        }
        const person = {
            name: 'ian'
        }
        const bindFunc = func.myBind(person, 1, 2)
        const res = bindFunc(3,4)
        console.log(res)

小结:

        通过上述代码的实现,让我对bind,apply,call方法的较为底层逻辑更加了解,在日后编写代码时可以更加恰当清楚的了解我需要什么,怎么使用。同时我对this的指向、意义、性质更为了解

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值