this

函数上下文中的this

<script>
    // 如果要把this的值从一个环境传到另一个,就要用call或apply。

    // 对象可以作为bind或apply的第一个参数传递,并且该参数将绑定到this
    var obj = {a: 'Custom'};

    // 声明一个变量,并将该变量作为全局对象window的属性
    var a = 'Global';

    function whatThis() {
        return this.a;  // this的值取决于函数被调用的方式
    }

    // 'Global' 因为这个函数中this没有被设定,所以它默认是全局window对象。
    whatThis();
    // ’Custom' 因为函数中this被设置为obj
    whatThis.call(obj);
    // ’Custom' 因为函数中this被设置为obj
    whatThis.apply(obj);
</script>

 

this和对象转换

<script>  
    function add(c, d) {
        return this.a + this.b + c + d;
    }

    var o = {a: 1, b: 3};
    // 第一个参数是用作"this"的对象,其余参数用作函数的参数(其中一个参数是数组,则数组成员用作函数参数)
    add.call(o, 6, 8);  // 18
    add.apply(o, [10, 20]); // 34
</script>

<script>
    /*
    在非严格模式下使用call和apply时,如果用作this的值不是对象,则会被尝试转换为对象。
    null和undefined被转换为全局对象。原始值如”7“或”foo“会使用相应构造函数转换为对象。
    因此”7“会被转换为new Number(7)生成的对象,字符串“foo”会转换为new String('foo')生成的对象。
    */
    function bar() {
        console.log(Object.prototype.toString.call(this));
    }
    bar.call(7);  //[Object Number]
    bar.call('foo');  // [Object String]
    bar.call(undefined);  // [Object Window]
</script>

  

bind方法

<script>
    /*
    Function.prototype.bind():调用f.bind(someObject)会创建一个与f具有相同函数体
    和作用域的函数,但是在这个新函数中,this将永久地绑定到bind的第一个参数,无论这个函数
    函数时如何被调用的。
    */

    function f() {
        return this.a;
    }

    var g = f.bind( {a: "azerty"} );
    console.log(g());  // azerty 按照bind上述bind注释,g函数将和f一样拥有相同函数体和作用域,那this也将永远指向对象:{a: "azerty"}

    var h = g.bind( {b: "yoo"} );
    console.log(h());  // azerty 重新绑定新对象没用,只指向{a: "azerty"}

    var o = {
        a: 37,
        f: f,
        g: g,
        h: h
    };
    debugger;
    console.log(o.a);   // 37
    console.log(o.f()); // 37
    console.log(o.g()); // azerty
    console.log(o.h()); // azerty
</script>

 

箭头函数

<script>
    /*
    箭头函数中,this与封闭词法环境的this保持一致,在全局代码中,它将被设置为全局对象:
    */
    debugger;
    var globalObject = this;
    var foo = (() => this); // function foo() {return this}
    console.log(foo() === globalObject);

    // 作为对象一个方法调用
    var obj = {foo: foo};
    console.log(obj.foo() === globalObject); //true

    // 尝试使用call来设定this
    console.log(foo.call(obj) === globalObject);  // true

    // 尝试使用bind来设定this
    foo == foo.bind(obj);
    console.log(foo() === globalObject );  // true
</script>

<script>
    /*
    创建一个含有bar方法的obj对象,
    bar返回一个函数,
    这个函数返回this,
    这个返回的函数是以箭头函数创建的,
    所以它的this被永久绑定到了它外层函数的this。
    bar的值可以在调用中设置,这反过来又设置了返回函数的值
    */

    var obj = {
        bar: function() {
            var x = (() => this);
            return x;
        }
    };

    debugger;
    /*
    作为obj对象的一个方法来调用bar,把它的this绑定到obj。
    将返回的函数的引用赋值给fn
    */
    var fn = obj.bar();

    /*
    * 直接调用fn而不设置this,
    * 通常(即不使用箭头函数的情况)默认为全局对象
    * 若在严格模式则为undefined
    */
    console.log(fn() === obj); // true

    /*
    * 但是注意,如果你只是引用obj的方法,
    * 而没有调用它
    */
    var fn2 = obj.bar;

    /*那么调用箭头函数后,this指向window,因为它从bar继承this*/
    console.log(fn2()() == window); // true
</script>

 

作为构造函数

<script>
    /*
    当一个函数用作构造函数时(使用new关键字),它的this被绑定到正在构造的新对象。
    虽然构造函数返回默认值是this所指的那个对象,但它仍可以手动设置返回其他对象
    (如果返回值不是一个对象,则返回this对象)
    */

    /*
    构造函数这样工作:
    functin MyCostructor(para) {
        // 函数实体写在这里
        // 根据需要在this上创建属性,然后赋值给它们,比如:
        this.fum = "nom";
        // 等等……

        // 看到这里,对以前看过的内容有了新的理解,this.fum是在为对象增加属性值,
        // 而哪个对象使用这个函数作为构造函数,则this指向哪个对象,fum也作为哪个对象的属性值。
        this.ele = para; //  this.para = para
        // 字符串被赋值是要加上双引号的,若字符没有双引号作为值,那它就是变量。
        // 故this.para = para可以看做this.para是对象有个名为para的属性(属性值不可变),
        // 等号右侧的para是变量值,它可以是任何类型值,具体是要看构造时传入的是什么类型(字符串就是双引号)
        // 啊……知识的海洋里又看到一点希望~~~

        // 如果函数具有返回对象的return语句,则该对象将是new表达式的结果。
        // 否则,表达式的结果是当前绑定到this的对象(即通常常见的情况~)
        // 即this 将是指向被return的对象,而不是用构造函数创建的对象。
    }
    */

    // 通常常见的情况
    function C() {
        this.a = 36;
    }

    var o = new C();
    console.log(o.a);  // 36

    // 构造函数返回值为对象
    function C2() {
        this.a = 36;
        this.b = 545;
        return { a: 32, c: 666 };
    }

    o = new C2();
    console.log(o.a); // 32
    console.log(o.b); // undefined
    console.log(o.c); // 666

</script>

 

this范围

<script>
    var name = '希望';
    var age = 17;

    var obj = {
        name: '校长',
        objAge: this.age, // 这里的this指向window
        myFun: function() {
            // 这里的this指向obj
            console.log(this.name + " 年龄 " + this.age);
        }
    }

    debugger;
    obj.objAge;  // 17
    obj.myFun(); // 校长 年龄 undefined

</script>

 

posted @ 2021-06-22 11:39  し7709  阅读(68)  评论(0编辑  收藏  举报