博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
javascript系列之this总结
阅读量:6359 次
发布时间:2019-06-23

本文共 5690 字,大约阅读时间需要 18 分钟。

在 JavaScript 中,this 是指当前函数中正在执行的上下文环境:

  • 函数调用
  • 方法调用
  • 构造函数调用
  • 间接调用
  • 绑定函数调用
  • 箭头函数
  • 易错场景

函数调用

函数调用 代表了该函数接收以成对的引号包含,用逗号分隔的不同参数组成的表达式。

函数调用中的this

function sum(a, b) {        console.log(this === window); // => true      this.myNumber = 20; // 在全局对象中添加 'myNumber' 属性      return a + b;    }    // sum() 为函数调用    // this 在 sum() 中是全局对象 (window)    sum(15, 16);     // => 31      window.myNumber; // => 20

当 sum(15, 16) 被调用时,JavaScript 自动将 this 设置为全局对象,即 window。

严格模式下,函数调用中的 this

严格模式由 ECMAScript 5.1 引进,用来限制 JavaScript 的一些异常处理,提供更好的安全性和更强壮的错误检查机制。使用严格模式,只需要将 'use strict' 置于函数体的顶部。这样就可以将上下文环境中的 this 转为 undefined。这样执行上下文环境不再是全局对象,与非严格模式刚好相反。

function multiply(a, b) {        'use strict'; // 开启严格模式      console.log(this === undefined); // => true      return a * b;    }    // 严格模式下的函数调用 multiply()     // this 在 multiply() 中为 undefined    multiply(2, 5); // => 10

严格模式不仅在当前作用域起到作用,它还会影响内部作用域,即内部声明的一切内部函数的作用域。

function execute() {        'use strict'; // 开启严格模式      function concat(str1, str2) {        // 内部函数也是严格模式        console.log(this === undefined); // => true        return str1 + str2;      }      // 在严格模式下调用 concat()      // this 在 concat() 下是 undefined      concat('Hello', ' World!'); // => "Hello World!"    }    execute();

方法调用

当在一个对象里调用方法时,this 代表的是对象它自身。

严格模式不仅在当前作用域起到作用,它还会影响内部作用域,即内部声明的一切内部函数的作用域。

var calc = {        num: 0,      increment: function() {        console.log(this === calc); // => true        this.num += 1;        return this.num;      }    };    // 方法调用,this 指向 calc    calc.increment(); // => 1      calc.increment(); // => 2

构造函数调用

function Foo () {        console.log(this instanceof Foo); // => true      this.property = 'Default Value';    }    // 构造函数调用    var fooInstance = new Foo();      fooInstance.property; // => 'Default Value'

间接调用

间接调用表现为当一个函数使用了 .call() 或者 .apply() 方法。.call() 和 .apply() 被用来配置当前调用的上下文环境。

var rabbit = { name: 'White Rabbit' };      function concatName(string) {        console.log(this === rabbit); // => true      return string + this.name;    }    // 间接调用    concatName.call(rabbit, 'Hello ');  // => 'Hello White Rabbit'      concatName.apply(rabbit, ['Bye ']); // => 'Bye White Rabbit'
两个方法最主要的区别为 .call() 接收一组参数,而 .apply() 接收一串参数作为类数组对象传递。

绑定函数调用

绑定函数调用是将函数绑定一个对象,它是一个原始函数使用了 .bind() 方法。

方法 .bind(thisArg[, arg1[, arg2[, ...]]]) 接收第一个参数 thisArg 作为绑定函数在执行时的上下文环境,以及一组参数 arg1, arg2, ... 作为传参传入函数中。 它返回一个新的函数,绑定了 thisArg。
function multiply(number) {        'use strict';      return this * number;    }    // 创建绑定函数,绑定上下文2    var double = multiply.bind(2);      // 调用间接调用    double(3);  // => 6      double(10); // => 20
var numbers = {        array: [3, 5, 10],      getNumbers: function() {        return this.array;          }    };    // 创建一个绑定函数    var boundGetNumbers = numbers.getNumbers.bind(numbers);      boundGetNumbers(); // => [3, 5, 10]      // 从对象中抽取方法    var simpleGetNumbers = numbers.getNumbers;      simpleGetNumbers(); // => undefined 或者严格模式下抛出错误
.bind() 创建了一个永恒的上下文链并不可修改。一个绑定函数即使使用 .call() 或者 .apply()传入其他不同的上下文环境,也不会更改它之前连接的上下文环境,重新绑定也不会起任何作用。
function getThis() {        'use strict';      return this;    }    var one = getThis.bind(1);      // 绑定函数调用    one(); // => 1      // 使用 .apply() 和 .call() 绑定函数    one.call(2);  // => 1      one.apply(2); // => 1      // 重新绑定    one.bind(2)(); // => 1      // 利用构造器方式调用绑定函数    new one(); // => Object
补充bind用法
bind()的另一个最简单的用法是使一个函数拥有预设的初始参数。这些参数(如果有的话)作为bind()的第二个参数跟在this(或其他对象)后面,之后它们会被插入到目标函数的参数列表的开始位置,传递给绑定函数的参数会跟在它们的后面。
function list() {      return Array.prototype.slice.call(arguments);    }        var list1 = list(1, 2, 3); // [1, 2, 3]        // Create a function with a preset leading argument    var leadingThirtysevenList = list.bind(undefined, 37);        var list2 = leadingThirtysevenList(); // [37]    var list3 = leadingThirtysevenList(1, 2, 3); // [37, 1, 2, 3]

箭头函数

箭头函数的设计意图是以精简的方式创建函数,并绑定定义时的上下文环境。

箭头函数并不创建它自身执行的上下文,使得 this 取决于它在定义时的外部函数。
class Point {        constructor(x, y) {        this.x = x;        this.y = y;      }      log() {        console.log(this === myPoint); // => true        setTimeout(()=> {          console.log(this === myPoint);      // => true          console.log(this.x + ':' + this.y); // => '95:165'        }, 1000);      }    }    var myPoint = new Point(95, 165);      myPoint.log();
箭头函数一次绑定上下文后便不可更改,即使使用了上下文更改的方法.
var numbers = [1, 2];      (function() {        var get = () => {        console.log(this === numbers); // => true        return this;      };      console.log(this === numbers); // => true      get(); // => [1, 2]      // 箭头函数使用 .apply() 和 .call()      get.call([0]);  // => [1, 2]      get.apply([0]); // => [1, 2]      // Bind      get.bind([0])(); // => [1, 2]    }).call(numbers);

易错场景

this 在内部函数中

var numbers = {        numberA: 5,      numberB: 10,      sum: function() {        console.log(this === numbers);        // => true        function calculate() {          console.log(this === numbers);      // => false          return this.numberA + this.numberB;        }        return calculate();      }    };    numbers.sum();

解决办法:return calculate.call(this);

this在回调函数中

function Animal(type, legs) {        this.type = type;      this.legs = legs;        this.logInfo = function() {        console.log(this === myCat);       // => false        console.log('The ' + this.type + ' has ' + this.legs + ' legs');      }    }    var myCat = new Animal('Cat', 4);      setTimeout(myCat.logInfo, 1000);

解决办法:setTimeout(myCat.logInfo.bind(myCat), 1000);

把包含this的方法赋给一个变量

var name = "aa";    var user = {       name: 'hhh',       sayName: function(){           console.log(this.name);       }   }   var test = user.sayName;   test();   // aa

解决办法:var test = user.sayName.bind(user);

参考链接

转载地址:http://vvbma.baihongyu.com/

你可能感兴趣的文章
WebSocket跨域问题解决
查看>>
世界经济论坛发布关于区块链网络安全的报告
查看>>
巨杉数据库加入CNCF云原生应用计算基金会,共建开源技术生态
查看>>
Ubuntu 16.04安装Nginx
查看>>
从 JS 编译原理到作用域(链)及闭包
查看>>
flutter 教程(一)flutter介绍
查看>>
CSS面试题目及答案
查看>>
【从蛋壳到满天飞】JS 数据结构解析和算法实现-Arrays(数组)
查看>>
Spring自定义注解从入门到精通
查看>>
笔记本触摸板滑动事件导致连滑的解决方式
查看>>
Runtime 学习:消息传递
查看>>
你了解BFC吗?
查看>>
linux ssh tunnel使用
查看>>
十、详解FFplay音视频同步
查看>>
自定义元素探秘及构建可复用组件最佳实践
查看>>
小猿圈Python教程之全面解析@property的使用
查看>>
mpvue开发小程序所遇问题及h5转化方案
查看>>
View和Activity的生命周期
查看>>
Throwable是一个怎样的类?
查看>>
三条代码 搞定 python 生成验证码
查看>>