Skip to content

作用域

根据名称查找变量的规则。

词法作用域

定义在词法阶段的作用域,也就是写代码的时候,把变量命名在哪决定的。

函数作用域

函数花括号内部的全部变量,在函数内部使用。

闭包

函数嵌套函数,内层函数引用了外层函数作用域下的变量,并且内层函数在全局作用域下可以访问,就形成了闭包。这是一种现象。

  • 应用场景:闭包是用来保存执行环境的。

this的指向

this的指向,是根据上下文动态决定的,他永远返回一个对象或者undefined

  • 在简单调用时,this 默认指向的是window / global / undefined / (浏览器/node/严格模式)
  1. 对象调用时,绑定在对象上
  2. 使用call,apply,bind时,绑定在指定的参数上
  3. 在使用new关键词的时候,绑定到新创建的对象上(以上三条优先级:new > apply/call/bind > 对象调用)
  4. 使用箭头函数,根据外层规则决定

箭头函数不可以作为构造函数

js
function test() {
    return this
}
console.log(test.call(4))  // [Number: 4] 包装对象
js
    const foo = {
        bar: 10,
        fn: function () {
            console.log(this)
            console.log(this.bar)
        }
    }
    var fn1 = foo.fn;

    fn1();    // global undefined
    foo.fn();    // foo 10
js
    const person = {
        name: "luyi",
        brother: {
            name: 'yunyin',
            fn: function () {
                return this.name
            },
            fn2: () => {
                return this.name
            }
        }
    }
    console.log(person.brother.fn());  // yunyin
    console.log(person.brother.fn2());  //undefined
js
    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()  // 这里的this指向了全局
        }
    }
    console.log(o1.fn()) // o1
    console.log(o2.fn()) // o1
    console.log(o3.fn()) // undefined  说明只看方法前面是谁调用的
js
window.id = 'window';
document.getElementById('div1').onclick = function () {
    console.log(this.id); // div1
    const callback = function () {
        console.log(this.id); //因为是普通函数调用,所以this 指向 window
    }
    callback();
}
js
var obj = {
    name: "jone",
    arr: [1, 2, 3],
    print() {
        this.arr.forEach(function (v) {
            console.log(this.name);
        })
    }
}
obj.print(); // undefined undefined undefined
js
    var number = 5;  // 10 20
    var obj = {
        number: 3, // 6
        fn1: (function () {
            var number;  // 3 9 27
            this.number *= 2;
            number = number * 2;
            number = 3;
            return function () {
                var num = this.number;
                this.number *= 2;
                console.log(num);
                number *= 3;
                console.log(number);
            }
        })()
    }
    var fn1 = obj.fn1;
    fn1.call(null);
    obj.fn1();
    console.log(window.number);

    // 10 9 3 27 20

call、apply、bind

都可以修改this指向,只不过bind绑定以后返回新的方法不执行,而apply传递数组

call与bind联用

js
// call 方法来源于Function.prototype
// 这里相当于改写了 slice 方法
var slice = Function.prototype.call.bind(Array.prototype.slice)
console.log(slice([1, 2, 3], 0, 1)); // [1]

上文中,.bind(Array.prototype.slice)Array.prototype.slice永久绑定给了这里的call作为this传入。

如果不理解看看这个:console.log(Array.prototype.slice.call([1, 2, 3], 0, 1))

还不理解再看看这个:console.log([1, 2, 3].slice(0, 1))

鄂ICP备2024055897号