JavaScript中的this

字号+ 编辑: 秦朝 修订: 秦朝 来源: 腾讯QQ兴趣部落 2015-02-07 11:34:10 我要说两句(0)

在js中,this这个上下文总是变化莫测,很多时候出现bug总是一头雾水,其实,只要分清楚不同的情况下如何执行就ok了。

全局执行

首先,我们在全局环境中看看它的 this 是什么:

first. 浏览器:

console.log(this);// Window
{
    speechSynthesis: SpeechSynthesis,
    caches: CacheStorage,
    localStorage: Storage,
    sessionStorage: Storage,
    webkitStorageInfo: DeprecatedStorageInfo…
}

  可以看到打印出了 window 对象;

  second. node:

console.log(this);// global

  可以看到打印出了 global 对象;

  总结:在全局作用域中它的 this 执行当前的全局对象(浏览器端是 Window,node 中是 global)。

函数中执行

var obj = {
    name: 'qiutc',
    foo: function() {
        console.log(this);
    },
    foo2: function() {
        console.log(this);
        setTimeout(() => {
            console.log(this);  // Object
            {name: "qiutc"}
        }, 1000);
    }
}
obj.foo2();

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。

根据例子我们理解一下这句话:

在 obj.foo2() 执行的时候,当前的 this 指向 obj;在执行 setTimeout 时候,我们先是定义了一个匿名的箭头函数,关键点就在这,箭头函数内的this 执行定义时所在的对象,就是指向定义这个箭头函数时作用域内的 this,也就是 obj.foo2 中的 this,即 obj;所以在执行箭头函数的时候,它的 this -> obj.foo2 中的 this -> obj;

简单来说, 箭头函数中的 this 只和定义它时候的作用域的 this 有关,而与在哪里以及如何调用它无关,同时它的 this 指向是不可改变的。

call, apply, bind

在 js 中,函数也是对象,同样也有一些方法,这里我们介绍三个方法,他们可以更改函数中的 this 指向:

apply

fun.apply(thisArg[, [arg1, arg2, ...]])

它会立即执行函数,第一个参数是指定执行函数中 this 的上下文,第二个参数是一个数组,是传给执行函数的参数(与 call 的区别);

bind

var foo = fun.bind(thisArg[, arg1[, arg2[, ...]]]);

它不会执行函数,而是返回一个新的函数,这个新的函数被指定了 this 的上下文,后面的参数是执行函数需要传入的参数;

这三个函数其实大同小异,总的目的就是去指定一个函数的上下文(this),我们以 call 函数为例;

为一个普通函数指定 this

var obj = { name: 'qiutc' };
function foo() {
    console.log(this);
}
foo.call(obj); // Object {name: "qiutc"}

可以看到,在执行 foo.call(obj) 的时候,函数内的 this 指向了 obj 这个对象,成功;

为对象中的方法指定一个 this

var obj = {
    name: 'qiutc',
    foo: function () {
        console.log(this);
    }
}
var obj2 = {
    name: 'tcqiu222222'
};
obj.foo.call(obj2);// Object {name: "tcqiu222222"}

可以看到,执行函数的时候这里的 this 指向了 obj2,成功;

为构造函数指定 this

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var p = new Person.call(obj, 'qiutc');// Uncaught TypeError: Person.call is not a constructor(…)

这里报了个错,原因是我们去 new 了 Person.call 函数,而非 Person ,这里的函数不是一个构造函数;

换成 bind 试试:

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var Person2 = Person.bind(obj);
var p = new Person2('qiutc');// Person {name: "qiutc"}console.log(obj);// Object {name: "qiutc2222222"}

打印出来的是 Person 实例化出来的对象,而和 obj 没有关系,而 obj 也没有发生变化,说明,我们给 Person 指定 this 上下文并没有生效;

因此可以得出: 使用 bind 给一个构造函数指定 this,在 new 这个构造函数的时候,bind 函数所指定的 this 并不会生效;

当然 bind 不仅可以指定 this ,还能传入参数,我们来试试这个操作:

function Person(name) {
    this.name = name;
    console.log(this);
}
var obj = {
    name: 'qiutc2222222'
};
var Person2 = Person.bind(obj, 'qiutc111111');
var p = new Person2('qiutc');// Person {name: "qiutc111111"}

可以看到,虽然指定 this 不起作用,但是传入参数还是起作用了;

 为箭头函数指定 this

我们来定义一个全局下的箭头函数,因此这个箭头函数中的 this 必然会指向全局对象,如果用 call 方法改变 this 呢:

var afoo = (a) => {
    console.log(a);
    console.log(this);
}
afoo(1);// 1// Window
var obj = {
    name: 'qiutc'
};
afoo.call(obj, 2);// 2// Window

可以看到,这里的 call 指向 this 的操作并没有成功,所以可以得出: 箭头函数中的 this 在定义它的时候已经决定了(执行定义它的作用域中的 this),与如何调用以及在

阅完此文,您的感想如何?
  • 鼓掌

    0

  • 鄙视

    0

  • 开心

    0

  • 愤怒

    0

  • 可怜

    0

1.转来的文章都会标好来源,如对来源资料存疑,请邮件声明;
2.本站标注原创的文章,转发时烦请注明来源;
3.如文章侵犯了您的版权,请通知本站,该文章将在24小时内移除。

相关课文
  • JS的Timeout定时器怎么写成无限循环的?

    JS的Timeout定时器怎么写成无限循环的?

  • 并肩比较React Native和Ionic

    并肩比较React Native和Ionic

  • jQuery select下拉框的选中事件

    jQuery select下拉框的选中事件

  • CKPayer6.3如何替换logo

    CKPayer6.3如何替换logo

我要说说
网上宾友点评