要讲普通函数的this就不得不讲执行时的作用域和作用域链,要讲箭头函数的this就不得不说词法作用域。这里主讲词法作用域。

词法作用域可以动态更改:使用eval()函数,传入字符串,但是在严格模式下eval有自己的词法作用域,意味着无法更改所在的作用域。(还有其他方法,总的来说要避免动态生成代码)

大量使用eval和with会使代码运行的很慢,引擎不能静态对其进行优化,也就是所有的优化可能都是无效的。


this:在不同情况下含义不同,分别是构造函数、上下文(默认绑定为全局对象)、严格模式、call(apply、bind)调用。


普通函数的this

        // 1. 普通函数的this指向调用者,
        // 2. 或者没有调用者则是全局对象

        var id = '全局对象id'

        function foo2() {
            console.log(this)// [object Window]

            function foo() {
                var id = '函数内部的id';
                setTimeout(function () {
                    console.log('普通函数this.id:', this.id); //全局对象id
                    console.log('普通函数作用域链的id:', id) //函数内部的id
                }, 1000)

                //setTimeout的调用者为 全局对象 window

                console.log(this)// [object Window]

                setTimeout(() => {
                    console.log(this)// [object Window]
                    console.log('箭头函数this.id:', this.id);//全局对象id
                    console.log('箭头函数作用域链的id:', id);//函数内部的id
                }, 100)
            }
            foo()
        }

        foo2()

由此代码可以看出处于同一个外层函数内,无论嵌套多少层,对于箭头函数来说,都是该外层函数所处的作用域,即父级作用域(希望能深刻理解作用域)

箭头函数的this

        //对象里的箭头函数的this
        var count = 2;
        function test() {
            var count = 3;
            console.log(this) // window
            var obj = {
                count: 0,
                cool: () => {
                    if (this.count > 1) {
                        //------------------------------------
                        var bbb = () => {
                            console.log(this) // window
                            var ccc = () => {
                                console.log(this) // window
                            }
                            ccc()
                        }
                        console.log(this) // window
                        bbb()
                        //------------------------------------
                        function bbb2() {
                            console.log(this) // window
                            function aaa() {
                                console.log(this) // window
                            }
                            aaa()
                        }
                        console.log(this) // window
                        bbb2()
                    }

                }
            };
            obj.cool()
        }
        test()

这些例子想说明的是,他总是在寻找最外层的作用域,而俗称理解的“父级作用域”,让我又深思作用域的概念。 其实箭头函数的this,就是为了解决下面这个代码:

var self = this;

所以,弄不明白的话,会用就好了,接下来再去深究一下作用域的概念。


  • 默认绑定为全局对象: alt

  • 一个总结图(call分类那里是call和apply,写错了)

图片说明


bind是创建一个新函数,对新的这个进行重新绑定是不行的,但是对于原来的是可以的,如果不保存bind后的函数,就凭空消失掉啦,没有任何影响。

alt