zoukankan      html  css  js  c++  java
  • [Node.js] 也说this

    原文地址:http://www.moye.me/2014/11/21/也说this/

    引子

    Any sufficiently advanced technology is indistinguishable from magic.

    — Arthur C.Clarke

    老爷子所言不虚,各种技术里都有黑魔法,比如JavaScript,就有着像 this 这样的奇葩存在。

    What's this?

    this是什么?大概能得到的答案有:

    • 当前方法引用的对象实例
    • 当前调用函数本身
    • 全局上下文(顶层对象)
    • 函数运行的context环境

    哪种解释是对的呢?来看段代码:

    function foo() {
        console.log(this.a);
    }
    var a = 2;
    var obj = {a: 1};
    foo();         // 2 (在Node下是undefined)
    foo.call(obj); // 1
    obj.foo = foo;
    obj.foo();     // 1

    在这段代码中,this 呈现了三种可能:

    1. 全局上下文:foo执行时,this 开放式的指向了全局上下文(在node下为undefined,原因在于Global的作用域与浏览器不同
    2. 向方法传递的上下文:Function对象固有的applycall方法,第一个参数均为 thisArg,它将被调用函数做为执行的上下文(在非strict模式,如果这个值为null或undefined,将有污染全局上下文的风险
    3. 方法引用的对象:可以将这个对象看成new创建的对象,函数的this将指向它

    看起来是要有无限可能的节奏……好在我提前找到了这本书:

    You Don't Know JS: this & Object Prototypes

    You Don't Know JS: this & Object Prototypes

    To learn this, you first have to learn what this is not, despite any assumptions or misconceptions that may lead you down those paths. this is neither a reference to the function itself, nor is it a reference to the function’s lexical scope.

     

    this is actually a binding that is made when a function is invoked, and what it references is determined entirely by the call-site where thefunction is called.

     

    this 绑定上下文

    this 实质上是一种绑定(binding)机制,只关乎函数被调用时所处的 上下文(context),而不关心它在哪里被定义。举个粟子:

    function foo(something) {
        this.a = something;
    }
    var obj1 = {
        foo: foo
    };
    var obj2 = {};
    obj1.foo( 2 );
    console.log( obj1.a ); // 2
    obj1.foo.call( obj2, 3 );
    console.log( obj2.a ); // 3
    var bar = new obj1.foo( 4 );
    console.log( obj1.a ); // 2
    console.log( bar.a ); // 4
    

    this做为一个被绑定的context,甚至与函数依附的对象无关,通过obj1.foo.call( obj2, 3 )一句我们能看清:这个context被引入,函数既可以读也可以修改它,但这里涉及到一个优先级问题,即:为什么 obj1绑定的this.a 没有被foo()改写,却是 obj2的 this.a?

    this 绑定优先级

    绑定 this 的形式大概有以下几种,它们的优先级如下排列:

    1. 被new过的函数实例,那么函数里的this绑定的就是这个实例对象本身,如 var bar = new foo();
    2. 函数是被 call 或者 apply 调用,那么 this 绑定的是第一个参数: var bar = foo.call( obj2 );
    3. 函数是被某个对象引用的方法,那么它的this 绑定的是这个对象:var bar = obj1.foo();
    4. 最后,就是隐式绑定了,这种情况的this 绑定的是全局上下文,在 strict mode(Node)下是 undefined:var bar = foo();

    建议

    对于闭包惯用的self = this技俩,You Don't Know JS 一书是不提倡的,它的建议是:

    Embrace  this-style mechanisms completely, including using bind(..) where necessary, and try to avoid  self = this ...

    Function.prototype.bind,它的实现看起来是这样的:

    if (!Function.prototype.bind) {
        Function.prototype.bind = function (oThis) {
            if (typeof this !== "function") {
                // closest thing possible to the ECMAScript 5
                // internal IsCallable function
                throw new TypeError(
                    "Function.prototype.bind - what is trying " +
                    "to be bound is not callable"
                );
            }
            var aArgs = Array.prototype.slice.call(arguments, 1),
                fToBind = this,
                fNOP = function () {
                },
                fBound = function () {
                    return fToBind.apply(
                        (this instanceof fNOP && oThis ? this : oThis),
                        aArgs.concat(Array.prototype.slice.call(arguments))
                    )
                };
            fNOP.prototype = this.prototype;
            fBound.prototype = new fNOP();
            return fBound;
        };
    }
    

     

    更多文章请移步我的blog新地址: http://www.moye.me/  

  • 相关阅读:
    jquery获取html元素的绝对位置和相对位置的方法
    Python基础之集合
    Python基础之集合
    PAT 甲级 1009 Product of Polynomials (25)(25 分)(坑比较多,a可能很大,a也有可能是负数,回头再看看)...
    PAT 甲级 1009 Product of Polynomials (25)(25 分)(坑比较多,a可能很大,a也有可能是负数,回头再看看)
    Python将数据写入excel或者txt,读入csv格式或xls文件,写入csv(写一行空一行解决办法)...
    Python将数据写入excel或者txt,读入csv格式或xls文件,写入csv(写一行空一行解决办法)
    Django将.csv文件(excel文件)显示到网页上
    cuDNN下载地址和指南
    cuDNN下载地址和指南
  • 原文地址:https://www.cnblogs.com/moye/p/JavaScript_this.html
Copyright © 2011-2022 走看看