This in JavaScript

声明 本文仅为读书笔记并致力于理解Js中的this关键字。如有雷同,纯属巧合。原因有二,其一:有幸看了同一本书,其二:this这玩意已被说烂了~

  1. 为什么要用this?

    this提供了优雅的方式隐式传递对象的引用

    上实例:

    function sayEng(){
        console.log(this.name+":sayEng");
    }
    function sayChi(){
        console.log(this.name+":sayChi");
    }
    function stu(){
        name = "stu";
    }
    function tea(){
        name = "tea";
    }
    sayEng.call(stu);//stu:sayEng
    sayEng.call(tea);//tea:sayEng
    sayChi.call(stu);//stu:sayChi
    sayChi.call(tea);//tea:sayChi

    当不使用this时

    function sayEng(ctx){
        console.log(ctx.name+"sayEng");
    }
    function sayChi(ctx){
        console.log(ctx.name+"sayChi");
    }
    function stu(){
        name = "stu";
    }
    function tea(){
        name = "tea";
    }
    sayEng(stu);//stu:sayEng
    sayEng(tea);//tea:sayEng
    sayChi(stu);//stu:sayChi
    sayChi(tea);//stea:sayChi
    两种对比,可以看出当不使用this时,需手动显式传递一个上下文对象。而使用了this可以使得代码很精炼。而且传递上下文的方式会使得代码越来越混乱。
  2. 对this的误解
    1)指向自身(书中代码)

    function foo(num) {
        console.log( "foo: " + num );
     // count用于记录foo的被调用次数
        this.count++;
    }
    foo.count = 0;
    var i;
    for (i=0; i<10; i++) {
        if (i > 5) {
            foo( i );
        }
    }
    console.log( foo.count ); // 0 -- ??

    为什么是0,而不是4?原因在于,此时调用foo函数的是window,this的指向是window。
    解决办法有两种:
    其一,用foo代替this。也就是foo.count++。
    其二,强制this指向foo,通过call,或者apply。也就是在if里面改为foo.call(foo,i)。
    2)指向函数的作用域

    function foo() {
        var a = 2;
        this.bar();
    }
    function bar() {
        console.log( this.a );
    }
    foo(); //ReferenceError:a is not defined
    原因在于:调用foo的对象为window
  3. 绑定规则
    1)默认绑定
    若函数是直接使用不带任何修饰的函数引用的,它便是应用了默认绑定。this指向window,上面的实例可以佐证。
    p.s 当使用严格模式时,则不能将全局对象用于默认绑定
    2)隐式绑定

    function foo() {
        console.log( this.a );
    }
    var obj = {
        a: 2,
        foo: foo
    };
    obj.foo(); // 2

    本例就使用了默认绑定,this绑定在obj上。另外,对象属性引用链只有上一层或者说最后一层在调用位置中起作用。也即,obj1.obj2.foo(),this绑定在obj2中。
    但是,隐式绑定经常会有一个问题产生--隐式丢失

    function foo() {
        console.log( this.a );
    }
    var obj = {
        a: 2,
        foo: foo
    };
    var bar = obj.foo; // 函数别名
    var a = "oops,global";
    bar(); // "oops,globa"

    this的指向不再是obj,而变成了window。丢失了this的指向。同理还有当obj.foo作为参数传递时丢失,原因在于参数传递相当于两个步骤,一赋值,二参数传递。
    3)显示传递
    通过call、apply的方式,将this绑定在对象上。具体call、apply的使用方法见本人博客Call and Apply in JavaScript
    4)new绑定

    function foo(a) {
        this.a = a;
    }
    var bar = new foo( 2 );
    console.log( bar.a );// 2
    使用new调用时,会构造一个对象并将this指向进行绑定。如本例的foo上。
  4. 优先级
    new绑定>显示绑定>隐式绑定>默认绑定


本人较懒,部分代码原封不动摘抄自原著。还请见谅

转载于:https://www.cnblogs.com/zhaoww/p/5679571.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值