cvte面试题——关于this指向、闭包及原型链上属性初始化的问题

cvte面试题——关于this指向和闭包的问题


一、关于this指向

首先,我们通过邹佳乐学长的一个this指向问题来先检测一下自己对于this的掌握程度。

let obj2 = {
    
    
    name: 'obj2'
}

const obj = {
    
    
    name: 'obj',
    say1() {
    
    
        console.log(this.name)
    },
    obj1: {
    
    
        name: 'obj1',
        say2() {
    
    
            console.log(this.name);
        }
    },
    say3() {
    
    
        const fn = () => {
    
    
            console.log(this.name);
        }
        fn()
    },
    say4() {
    
    
        const fn = function () {
    
    
            console.log(this.name);
        }
        fn()
    },
    say5() {
    
    
        const fn = () => {
    
    
            console.log(this.name);
        }
        fn.call(obj2)
    },
    say6() {
    
    
        const fn = function () {
    
    
            console.log(this.name);
        }
        fn.call(obj2)
    }
}

let a = obj.say1
let b = obj.obj1.say2
a() //undefined
b() //undefined
obj.say1() //obj
obj.obj1.say2() //obj1
obj.say3()//obj
obj.say4()//undefined
obj.say5()//obj
obj.say6()//obj2

接下来是cvte中有关于this指向的题,

<script>
        var ctx = {
    
    _val:30};
        var _val = 10;
        function rootFn(){
    
    
            console.log(this._val);
            this._val = 20;
            function childFn(){
    
    
                console.log(this._val);
            }
            return childFn;
        }
        rootFn.apply(ctx)();
        console.log(ctx._val);
        //30  10   20
        //注:这里并没有形成闭包
    </script>

关键点:这里并没有形成闭包

总结:
1、对于普通函数来说,this->window
2、全局作用域下,this -> window
3、对于对象来说,谁调用函数谁就是this
4、new 的方式,this永远被绑定在实例上
5、箭头函数本身是没有this,继承外层上下文绑定的this(包裹箭头函数的第一个普通函数的this)
6、箭头函数使用bind,call,this无效
7、bind/call/apply 这些改变上下文的 API 了,对于这些函数来说,this 取决于第一个参数,8、如果第一个参数为空,那么就是 window
9、不管我们给函数 bind 几次,fn 中的 this 永远由第一次 bind 决定


二、关于闭包的有趣问题

<script>
        let x = 100;
        let y = 200;
        let funA = function (x) {
    
    
            x += 1;
            let y = 201;
            let funB = function () {
    
    
                console.log(x);
                console.log(y);
            }
            return funB;
        }
        let f = funA(101);
        f();
        //102 201
        //注:这里形成了闭包
    </script>

关键点:这里形成了闭包


三、原型链上属性初始化的问题

<script>
        //在构造函数中,通过this.xxx所访问的属性xxx,并不会查找原型链,
        //若对象本身没有属性xxx,则会直接添加一个属性,不会再到原型链中添加。
        //如下面的b = new B(789)中,
        //先通过查找原型链发现value确实存在,然后直接在b的属性中,即b.value = 789,而b.__proto__.value=456,并不会有影响。
        function A(){
    
    
            this.value =456;
            this.getValue = function(){
    
    
                console.log(this.value);
            }
        }
        function B(value){
    
    
            if(value) {
    
    
                this.value = value;
            }
        }

        const a = new A();
        const a2 = new A();
        B.prototype = a2;
        const  b = new B(789);
        const b2 = new B();
         a2.value = 123;
         a.getValue(); //456
         a2.getValue();//123
         b.getValue();//789
         b2.getValue();//123

</script>

在构造函数中,通过this.xxx所访问的属性xxx,并不会查找原型链,
若对象本身没有属性xxx,则会直接添加一个属性,不会再到原型链中添加。

如上面的b = new B(789)中,先通过查找原型链发现value确实存在,然后直接在b的属性中,即b.value = 789,而b.__proto__.value=456,并不会有影响。

通过谷歌浏览器进行断点调试证明:
断点处:31行。
当执行完成33行时,从这里即可说明上面的分析是正确的。
在这里插入图片描述

继续执行完34行代码时:b.__proto__、b2.__proto__中的属性同时被修改。
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_45664402/article/details/114763468