关于this的那些事

栏目: JavaScript · 发布时间: 5年前

内容简介:this表示关键字,也是一个常见的代词,经常来表示一个上下文对象,那上下文对象又是什么呢?上面代码我们主要关注一点就是执行上下文,在1、2的位置分别绑定me、you上下文对象,所以输出的是相对应的name值;在3位置前面定义了一个全局的name变量,并且在没有指定上下文环境被输出了,这也涉及到this的隐式绑定(在"this的绑定"讲会详细说明),绑定到了当前环境window。下面我们把`sayName`函数显式的传递上下文对象:
  1. 什么是this
  2. 词法作用域与动态作用域
  3. this的绑定

一、什么是this

this表示关键字,也是一个常见的代词,经常来表示一个上下文对象,那上下文对象又是什么呢?

var me = {
    name: 'JJ Yu'
};

var you = {
    name: 'Kim'
};

function sayName () {
    console.log(this.name);
}

// 1
sayName.call(me); // output: JJ Yu
// 2
sayName.call(you); // output: Kim

var name = 'global name';
// 3
sayName(); // output: global name复制代码

上面代码我们主要关注一点就是执行上下文,在1、2的位置分别绑定me、you上下文对象,所以输出的是相对应的name值;在3位置前面定义了一个全局的name变量,并且在没有指定上下文环境被输出了,这也涉及到this的隐式绑定(在"this的绑定"讲会详细说明),绑定到了当前环境window。

下面我们把`sayName`函数显式的传递上下文对象:

// 声明一个传递上下文参数的函数
function sayName (context) {
    console.log(context.name);
}

sayName(me); // output: JJ Yu
sayName(you); // output: Kim
复制代码

相比第一种(隐式绑定),显示传递上下文显得复杂,而且代码模式越复杂,这样传递上下文对象就会让代码越来越乱。

二、动态作用域和词法作用域

例1:

function increase (i) {
    // this不是指向函数本身,而是指向了调用函数的上下文环境`window`
    this.count++;
    console.log(i);
}
increase.count = 0;

for(var i = 0; i < 5; i++) {
    increase(i);
}
console.log(increase.count); // output: 0
// output:
// 0
// 1
// 2
// 3
// 4
// 0
复制代码

例2:

function increase (i) {
    // 修改了,把指向指定到`increase`
    increase.count++;
    console.log(i);
}
increase.count = 0;

for(var i = 0; i < 5; i++) {
    increase(i);
}
console.log(increase.count); // output: 5
// output:
// 0
// 1
// 2
// 3
// 4
// 5复制代码

例1中的this.count中的this并不是指向函数对象,而是在被调用时候指向了`window`;而例2使用`词法作用域`直接指定increase对象的count属性。

那为啥例1的this会被动态绑定到window对象呢?

// window
function increase (i) {
    // this不是指向函数本身,而是指向了调用函数的上下文环境`window`
    this.count++;
    console.log(i);
}

increase(0); // 等价于 window.increase(0)
             // 即是调用window下的方法,this指向window
复制代码

如果还有点不明白,来看下下面常见的场景:

var env = 'global';
function foo () {
    this.env = 'foo function';
    setTimeout(function () {
        console.log(this.env); // ?
        console.log(this === window); // true
    })
}

foo();

复制代码

那么问号那行会输出:foo function;

总结:

  1. 函数中的this不是指向函数本身也不指向函数的词法作用域(见例1)
  2. this的绑定是发生在函数被调用时,至于this指向谁取决于函数在哪里被调用

三、this的绑定

在前面我们已经总结了this的指向,也就是绑定,是发生在函数被调用时。

调用位置:即函数在代码中被调用的位置(不是声明的位置),在这里只提及一下。

1、默认绑定(见例1)

这里需要注意的严格模式(strict mode)不能将全局对象用于默认绑定,此时this会绑定到undefined。

function foo () {
    "strict mode";
    console.log(this.env);
}

var env = 'global';

foo(); // TypeError: this is undefined复制代码

但在严格模式下调用函数不影响默认绑定:

function foo () {
    "strict mode";
    console.log(this.env);
}

var env = 'global';

(function () {
    "strict mode";
    foo(); // output: global
})();复制代码

2、隐式绑定

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

var obj = {
    env: 'obj',
    foo: foo
}

obj.foo(); // output: obj复制代码

当foo()被调用时,它的前面加上了obj对象引用,调用位置会使用obj上下文来引用函数。

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

var obj = {
    env: 'obj',
    foo: foo // => window -> obj
}
var f = obj.foo; // => obj -> window
var env = 'global';
f(); // output: global 复制代码

3、显示绑定

Function对象包含call以及apply两个方法,用来指定this的指向。详细用法自行百度。

var obj = {
    name: 'JJ Yu'
}
var name = 'window';
function sayName () {
    console.log(this.name);
}

sayName(); // output: window

sayName.call(obj); // output: JJ Yu
复制代码

硬绑定

var obj = {
    name: 'JJ Yu'
}
function sayName () {
    console.log(this.name);
}
function forceBind () {
    sayName.call(obj);
}

setTimeout(forceBind);复制代码

es5提供了内置方法Function.prototype.bind:

var obj = {
    name: 'JJ Yu'
}
function sayName () {
    console.log(this.name);
}
setTimeout(sayName.bind(obj));复制代码

该方法返回一个硬编码(不知道是啥东东)的新函数,指定this的上下文以及调用原函数。

new绑定

var Person = function (name) {
    this.name = name;
    this.sayName = function () {
        console.log(this.name);
    }
}
var jj = new Person('JJ');

jj.sayName(); // output: JJ复制代码

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

史蒂夫·乔布斯传

史蒂夫·乔布斯传

[美] 沃尔特·艾萨克森 / 管延圻、魏群、余倩、赵萌萌、汤崧 / 中信出版社 / 2011-10-24 / 68.00元

这本乔布斯唯一授权的官方传记,在2011年上半年由美国出版商西蒙舒斯特对外发布出版消息以来,备受全球媒体和业界瞩目,这本书的全球出版日期最终确定为2011年11月21日,简体中文版也将同步上市。 两年多的时间,与乔布斯40多次的面对面倾谈,以及与乔布斯一百多个家庭成员、 朋友、竞争对手、同事的不受限的采访,造就了这本独家传记。 尽管乔布斯给予本书的采访和创作全面的配合,但他对内容从不干......一起来看看 《史蒂夫·乔布斯传》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

HTML 编码/解码
HTML 编码/解码

HTML 编码/解码

HEX HSV 转换工具
HEX HSV 转换工具

HEX HSV 互换工具