3.①this指向四种:默认,隐式,显示call apply bind,new构造函数②优先级③new构造函数有无return④手写new⑤严格模式指向⑥手写call,apply,bind

目录

一:this指向问题

优先级:箭头函数创建时的绑定>new构造函数绑定>显示绑定>隐式绑定>默认绑定

1.默认绑定:全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

2.隐式绑定规则:谁调用this就指向谁(作为对象方法调用)

3.显示绑定:直接修改this指向: call apply bind

①基本用法

②区别

③特殊的使用场景:

4.new构造函数中this指向构造函数的实例   

①当函数没有返回值 return  时

②当函数有返回值 return 时

二:this指向练习及注意事项

1.方法里面如果有 写 “use strict“严格模式 : this指向undefined  

2.   路人.调用者.方法名()   this指向看首先谁调用了他

3.如果方法被赋值给变量出现 “= ”等号 要小心这是普通函数 this指向window

三:手写new参考链接

1.思考new做了什么?

2.下述 手写new


一:this指向问题

优先级:箭头函数创建时的绑定>new构造函数绑定>显示绑定>隐式绑定>默认绑定

1.默认绑定:全局作用域或者普通函数中this指向全局对象window(注意定时器里面的this指向window)

2.隐式绑定规则:谁调用this就指向谁(作为对象方法调用)

3.显示绑定:直接修改this指向: call apply bind

    <script>
        function b(){
            console.log(this.age)
        }
        let a = {age:18}
        b.call(a)
        b.apply(a)
        b.bind(a)()
    </script>

①基本用法

  • b.call(a,参数,参数2,等等)          将b的this指向a

  • b.apply(a,[参数,参数2,等等])

  • b.bind(a,参数1,参数2,等等)()

  • 当被指向的是 undefined和null时 指向window;当被指向数字1时指向Number,字符串'123'指向String;...依次类推

  • "use strict" 严格模式下,当被指向的是 undefined和null时 就是指向undefined和null

②区别

  • 传递参数的方法不同
  • bind不是立即执行的,首次调用返回的是一个方法,后面要加()进行立即执行操作

③特殊的使用场景:

  • 只能用apply的情况:Math.max.apply(null,a)
        let a = [1,2,8,9,321]
        console.log(Math.max(1,2,8,9,321))  // 321
        // 出现问题 : 括号里面不能直接传递数组
        console.log(Math.max(a))  // NaN
        // 解决方法 : 用apply 当 bind指向null时,this指向为window
        console.log(Math.max.apply(null,a))  // 321
  • 只能用bind的情况(因为bind不是立即执行函数,调用bind只回返回一个方法)
<body>
    <button id="btn1">点击按钮1输出按钮2</button>
    <button id="btn2">修改了按钮指向</button>
    <script>
        let btn1 = document.getElementById('btn1')
        let btn2 = document.getElementById('btn2')
        btn1.onclick = function(){
            console.log(this.id)
        }.bind(btn2)
    </script>
</body> 

4.new构造函数中this指向构造函数的实例   

①当函数没有返回值 return  时

②当函数有返回值 return 时

  • 如果return的值是基本数据类型的话,则忽略return,直接返回实例化的对象
  • 如果return的值是引用类型的话,则不再返回实例化的对象,而是直接返回return返回的引用类型的值。
    <script>
        function jiBen(){
            this.name = '返回基本数据类型,'
            return 111
        }
        function yinYong(){
            this.name = '返回引用数据类型,'
            return [1,2,3,4,5]
        }
        console.log(new jiBen())   // jiBen {name: '返回基本数据类型,'}
        console.log(new yinYong()) // [1, 2, 3, 4, 5]
    </script>

二:this指向练习及注意事项

1.方法里面如果有 写 “use strict“严格模式 : this指向undefined  

2.   路人.调用者.方法名()   this指向看首先谁调用了他

3.如果方法被赋值给变量出现 “= ”等号 要小心这是普通函数 this指向window

三:手写new参考链接

1.思考new做了什么?

①创建一个空的对象

②将空对象的原型,指向于构造函数的原型

③将空对象作为构造函数的上下文(改变this指向)

④对构造函数有返回值的处理判断

  • 如果return的值是基本数据类型的话,则忽略return,直接返回实例化的对象
  • 如果return的值是引用类型的话,则不再返回实例化的对象,而是直接返回return返回的引用类型的值。

下述代码是new做了什么

    <script>
        function fn(){
            this.name = 'this应该是实例化对象,而不是window'
            console.log(this)  //3. this指向 window
        }
        console.log(new fn()) //1.结果返回了的就是一个 fn 空对象
        console.log(new fn().__proto__ === fn.prototype)  //2.实例化对象的隐式原型等于构造函数的显示原型
        fn()    //3.没new过的构造函数:this指向 window 我们应该改成指向为 实例化对象
    </script>

我们要写出一个方法:这个方法return的结果是构造函数的实例化对象

2.下述 手写new

    <script>
        function fn(){
            this.name = '自定义new方法'
            return 111
        }
        function myNew(fn,...args){
            let obj = {}    //1.  创建一个空对象
            // obj.__prototype = fn.prototype   
            // 2.  将空对象的原型,指向构造函数的原型
            Object.setPrototypeOf(obj,fn.prototype)  //这种写法和上面的是有区别的
            // 3.  将空对象作为构造函数的上下文(改变this指向)
            var res = fn.apply(obj,args)
            // 4.  对构造函数有返回值的处理判断
            return res instanceof Object ? res : obj
        }
        console.log(myNew(fn)) 
    </script>

四:手写call 参考链接

    <script>
        let a = {name:'羊'}
        let b = function(x,y){
            console.log(this)
            console.log(x+y)  //30
        }
        Function.prototype.call = function(a,...args){
            // 被传入的值如果不是 null 或 undefined a为a;如果是则为window(直接指向window)
            var a = a || window
            // 创造一个独一无二的属性b
            let b = Symbol('b')
            // 这个this应该为调用call方法的对象b;让 b 成为 a 的一个属性 
            a.b = this
            // res保存执行的结果
            let res = a.b(...args)
            // 删掉 仿造的 b 属性
            delete a.b
            return res
        }
        b.call(a,10,20)
        // 将b的this指向a
    </script>

五:手写apply

  •  apply和call不同的就是参数形式,apply是数组,所以直接用args表示,call用..args
    <script>
        let a = {name:'羊'}
        let b = function(x,y){
            console.log(this)
            console.log(x+y)  //30
        }
        //apply和call不同的就是参数形式,apply是数组,所以直接用args表示,call用..args
        Function.prototype.call = function(a,args){
            var a = a || window
            let b = Symbol('b')
            a.b = this
            let res = a.b(...args)
            delete a.b
            return res
        }
        b.call(a,[10,20])
    </script>

六:手写bind

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值