关于this的那些事

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

内容简介: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复制代码

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

查看所有标签

猜你喜欢:

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

Python编程

Python编程

[美]埃里克·马瑟斯 / 袁国忠 / 人民邮电出版社 / 2016-7-1 / CNY 89.00

本书是一本针对所有层次的Python 读者而作的Python 入门书。全书分两部分:第一部分介绍用Python 编程所必须了解的基本概念,包括matplotlib、NumPy 和Pygal 等强大的Python 库和工具介绍,以及列表、字典、if 语句、类、文件与异常、代码测试等内容;第二部分将理论付诸实践,讲解如何开发三个项目,包括简单的Python 2D 游戏开发如何利用数据生成交互式的信息图......一起来看看 《Python编程》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具

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

HEX HSV 互换工具