• 闭包和this


    一.闭包

    最开始理解闭包是在一个函数内部定义一个函数,可以在外面的环境里进行调用。现在对于闭包的理解是利用函数来保存作用域内的对象。

    理解闭包首先要理解执行上下文,变量对象,活动对象,作用域链。因为执行上下文在函数执行后会销毁,因此变量也同时消失,但是为了一些特殊的应用场景,因此需要在函数执行后依旧可以访问到函数内的变量。js语言将函数作为“一等公民”,可以作为参数进行传递,同时每个函数也拥有其作用域链,如果内部函数作为变量返回,那么它将带着它的作用域链一同返回。因为内部函数的作用域链中包含着外部函数的变量,函数声明和参数等,因此,外部函数即使被执行完了,变量也不会销毁,因为他们依旧被内部函数的作用域链引用。 举个例子:

    var scope = 'global scope';
    function foo() {
        var scope = 'local scope';
        return function bar() {
    	console.log(scope);
        }
    }
    foo()();

    执行结果是‘local scope’。因为在返回的bar函数被调用的时候,会先从自己的作用域链查找,没有的话会逐级再向上查找,直到找到scope对象,输出结果结束。

    二.this

    如果把上面的代码增加一句话,在返回的函数中输出this。

    var scope = 'global scope';
    function foo() {
        var scope = 'local scope';
        return function bar() {
    	console.log(scope);
            console.log(this);
        }
    }
    foo()();

    结果是’local scope’,’window’。this指向的是global对象,在浏览器中就是window。 对this的理解是:

    1)它是在解析函数的时候确定的,即执行上下文的一个属性,运行过程中并不会改变。

    function foo() {
        function bar () {
          ...
        }
        this = bar; //会报错
    }

    2)this根据调用函数的对象或者表达式形式确定。

    function foo() {
       console.log(this);   
    }
    foo();

    调用函数的对象是Global,即window

    var foo = {
       x:10,
       bar: function () {                
            console.log(this.x);      
       }   
    }
    var zoo = {
        x:20
    }
    zoo.bar = foo.bar;
    zoo.bar();
    foo.bar();

    输出20,10,调用函数的对象分别是zoo和foo

    x = 'global x';
    var foo = {
       x:'local x',
       bar: function () {        
            console.log(this.x);   
       }   
    }
    foo.bar();
    (foo.bar)();
    (foo.bar = foo.bar)();

    ()表达式并没有改变函数本身的调用值,因此返回‘local x’,赋值表达式改变了函数本身的调用值,因此返回‘global x’。

    3)new操作符调用的函数this指向构造函数对象

    当函数作为构造器被调用的时候:

    function A() {
      alert(this); // newly created object, below - "a" object
      this.x = 10;
    }
     
    var a = new A();
    alert(a.x); // 10

    在这种情况下,new操作符会生成一个新的对象,即构造函数定义的对象。 在对象创建之后,然后所有“A”函数中this的值会设置为新创建的对象。

    可以通过函数对this值进行人为干预:

    4)call和apply函数

    x = 'global x';
    var foo = {
       x:'local x',
       bar: function (n) {        
            console.log(this.x); 
            console.log(n);  
       }   
    }
    foo.bar.call({x:'call x'}, 'call');
    foo.bar.apply({x:'apply x'}, ['apply']);

    通过call和apply的第一个参数改变this的值。

    参考文章:

    ECMA-262-3 in detail. Chapter 3. This.

  • 相关阅读:
    java基础之多线程一:概述
    java基础之io流总结四:字符流读写
    java基础之io流总结三:字节流读写
    java基础之io流总结二:File类基本应用
    java基础之io流总结一:io流概述
    java基础之集合:List Set Map的概述以及使用场景
    java基础之集合长度可变的实现原理
    HDU 4770 Lights Against Dudely 暴力枚举+dfs
    HDU 4771 BFS + 状压
    Codeforces Round #269 (Div. 2) D
  • 原文地址:https://www.cnblogs.com/Candybunny/p/5463645.html
Copyright © 2020-2023  润新知