js复习:this

this

this既不指向函数自身也不指向函数的词法作用域
this实际上是在函数被调用时发生的绑定,它指向什么完全取决于函数在哪里被调用。

需要明确的是,this在任何情况下都不指向函数的词法作用域

function foo() {
    var a = 2;
    this.bar();
}

function bar() {
    console.log(this.a);
}

foo(); // ReferenceError: a is not defined
function identify() {
    return this.name.toUpperCase();
}

function speak() {
    var greeting = "Hello, I'm " + identify.call(this);
    console.log(greeting);
}

var me = {
    name: "Kyle"
};

var you = {
    name: "Reader"
};

identify.call(me); // KYLE
identify.call(you); // READER

speak.call(me); // Hello, 我是KYLE
speak.call(you); // Hello, 我是READER

function identify(context) {
    return context.name.toUpperCase();
}

function speak(context) {
    var greeting = "Hello, I'm " + identify (context);
    console.log(greeting);
}

identify(you); // READER
speak(me); //hello, I'm KYLE

判断函数计算函数调用次数

function foo(num) {
    console.log("foo: " + num);

    // 记录foo被调用的次数
    this.count++;
}

foo.count = 0;

var i;
for (i=0; i<10; i++) {
    if (i > 5) {
      foo(i);
    }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

// foo被调用了多少次?
console.log(foo.count); // 0 -- 什么?!

function foo(num) {
    console.log("foo: " + num);

    // 记录foo被调用的次数
    // 注意,在当前的调用方式下(参见下方代码), this确实指向foo
    this.count++;
}

foo.count = 0;

var i;

for (i=0; i<10; i++) {
    if (i > 5) {
      // 使用call(..)可以确保this指向函数对象foo本身
      foo.call(foo, i);
    }
}
// foo: 6
// foo: 7
// foo: 8
// foo: 9

// foo被调用了多少次?
console.log(foo.count); // 4

绑定规则

默认绑定

非严格模式下,this指向window全局
严格模式下,this指向undefined


function foo() {
    "use strict";
//如果使用严格模式(strict mode),则不能将全局对象用于默认绑定,因此this会绑定到undefined
    console.log(this.a);
}

var a = 2;

foo(); // TypeError: this is undefined
function foo() {
  //foo()运行在非strict mode下时,默认绑定才能绑定到全局对象;在严格模式下调用foo()则不影响默认绑定
    console.log(this.a);
}

var a = 2;

(function(){
    "use strict";

    foo(); // 2
})();

隐式绑定
function foo() {
    console.log(this.a);
}

var obj = {
    a: 2,
    foo: foo
};

obj.foo(); // 2

是foo()的声明方式,及其之后是如何被当作引用属性添加到obj中的。但是无论是直接在obj中定义还是先定义再添加为引用属性,这个函数严格来说都不属于obj对象。

当foo()被调用时,它的前面确实加上了对obj的引用。当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。因为调用foo()时this被绑定到obj,因此this.a和obj.a是一样的。

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

var obj2 = {
    a: 42,
    foo: foo
};

var obj1 = {
    a: 2,
    obj2: obj2
};

obj1.obj2.foo(); // 42
//对象属性引用链中只有上一层或者说最后一层在调用位置中起作用
        function foo() {
            console.log(this.a);
        }

        var obj = {
            a: 2,
            foo: foo
        };

        var bar = obj.foo; // 函数别名!

        var a = "oops, global"; // a是全局对象的属性

        bar(); // "oops, global"

虽然bar是obj.foo的一个引用,但是实际上,它引用的是foo函数本身,因此此时的bar()其实是一个不带任何修饰的函数调用,因此应用了默认绑定。

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

        function doFoo(fn) {
            // fn其实引用的是foo

            fn(); // <-- 调用位置!
        }

        var obj = {
            a: 2,
            foo: foo
        };

        var a = "oops, global"; // a是全局对象的属性

        doFoo(obj.foo); // "oops, global"

参数传递其实就是一种隐式赋值,因此我们传入函数时也会被隐式赋值

如果把函数传入语言内置的函数而不是传入你自己声明的函数,会发生什么呢?结果是一样的,没有区别

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

        var obj = {
            a: 2,
            foo: foo
        };

        var a = "oops, global"; // a是全局对象的属性

        setTimeout(obj.foo, 100); // "oops, global"
显示绑定
//硬绑定
function foo() {
    console.log(this.a);
}

var obj = {
    a:2
};

var bar = function() {
    foo.call(obj);
};

bar(); // 2
setTimeout(bar, 100); // 2

// 硬绑定的bar不可能再修改它的this
bar.call(window); // 2

function foo(something) {
    console.log(this.a, something);
    return this.a + something;
}

var obj = {
    a:2
};

var bar = function() {
    return foo.apply (obj, arguments);
};

var b = bar (3); // 2 3
console.log(b); // 5
优先级

显示绑定比默认优先级高


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

var obj1 = {
    a: 2,
    foo: foo
};

var obj2 = {
    a: 3,
    foo: foo
};

obj1.foo(); // 2
obj2.foo(); // 3

obj1.foo.call(obj2); // 3
obj2.foo.call(obj1); // 2

this四种绑定规则的优先级

  • 显式绑定 > 隐式绑定 > 默认绑定
  • new绑定 > 隐式绑定 > 默认绑定
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值