当前位置: 首页 > news >正文

再也不用担心this指向的问题了

某日,跟公司大牛交流学习进步的方法,大牛说:要善于总结,技术总结很重要。于是自己想动手写点东西,总结一下自己近期学到的一些技术点,踩到的坑,也算是对自己一个技术复盘与总结。(作者表达能力一般,可能有表达错误或不准确的地方,欢迎纠正与交流。第一次写,有点小激动0.0)。

在工作中或面试过程中,经常会碰到有关this指向的问题,似曾相识的场景,却总是被混淆分不清,中了面试官的套路。这段时间作者研究了下,简单总结一波

1,默认规则。举个栗子,代码如下:

var name = '小明';
function print() {
    console.log(this.name);  // '小明'
    console.log(this);   //window对象
}
print();  
复制代码

这里我们看到打印出来的是小明,this.name被解析成了全局对象,this指向的是window对象。why?为什么this会指向window呢,因为在本例中,函数调用时应用了this的默认绑定原则,因此this指向的是全局对象。那我们怎么判断当前应用了默认绑定呢,我们可以通过函数的调用位置来判断,我们发现print函数是直接调用的,不经过任何修饰。因此只能使用默认绑定,无法使用其他原则

2,隐式绑定

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

var obj = {
    a:2,
    foo:foo
}
obj.foo()  // 2
复制代码

这里我们看到foo函数的调用者是obj对象,此时this绑定到了obj上,所以this.a输出的是obj.a。这种情况称之为隐式绑定:当函数引用有上下文对象时,隐式绑定规则会把函数调用中的this绑定到这个上下文对象。好,这个时候我们应该对隐式绑定有个大概的了解,那当函数有多个引用的时候会怎么样呢?让我们来看一道题:

var obj = {
   a:1,
   foo:function() {
       console.log(this.a)
   }
}

var obj1 = {
    a:2,
    obj:obj
}
obj1.obj.foo()  // 1
复制代码

我们看到这种情况下this指向的是最后一层的对象上,即obj上。隐式绑定一定都是这样的吗,答案式否定的,这里面有一个坑:有些时候会发生隐式绑定丢失的情况。让我们来举例说明:

var a = 'hello world';

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

var obj = {
    a:1,
    foo:foo
}

var print = obj.foo;
print();    // hello world
复制代码

这里我们发现隐式绑定规则失效了,this.a输出的不是1,而是全局对象上的a。这又是怎么回事呢?其实print,obj.foo都是函数的引用。直接调用print函数式,相当于直接调用foo函数,是不是很熟悉呢?没错,是默认绑定,所以此时this指向的是window。所以说我们在判断是否是隐式绑定的时候需要仔细些,分清楚情况。

3,显示绑定

何为显示绑定?利用call(),apply(),bind()强制绑定this指向的我们称之为显示绑定。举个栗子:

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

var obj = {
    a:1
}

foo.call(obj);  // 1
复制代码

这里我们看到通过call方法将this强制绑定到了对象obj上。利用bind()函数绑定this的做法我们又称之为硬绑定,硬绑定之后当前函数的this指向无法再修改,举个栗子:

var a = 'hello world';

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

var obj = {
    a:1
}

var print = foo.bind(obj);
print();    // 1

// 利用call方法强制将this绑定在window上,但是失败了,this还是指向obj
print.call(window);   // 1
复制代码

call(),apply(),bind()这三个函数有什么区别,这里就不一一阐述了,有兴趣的同学可以去了解下。

4,new绑定

这个相信大家平时编程时会遇到过很多次,这里简单说明下,如下:

function Person(name) {
    this.name = name;
}
var p = new Person('小明');
console.log(p.name);    // 小明
复制代码

这种情况我们称之为new绑定。

this绑定的四种基本规则我们基本弄清楚了,那么它们的优先级是什么样的呢?这里我们直接给出结论,不在一一举例对比说明了,有兴趣的同学可以自己举例对比下。优先级:new绑定 > 显示绑定 > 隐式绑定 > 默认绑定。我们在判断this指向的时候可以按照这个优先级顺序来判断,绝大部分情况都可以适用。

参考文献:《你不知道的JavaScript》,很nice的一本书!
复制代码

相关文章:

  • 快速理解URL重写
  • 12月,1000人,来一场属于敏捷人的重逢吧!
  • 话里话外:成功CEO的用人之道——按需激励
  • 001-ant design pro 页面加载原理及过程,@connect 装饰器
  • 对ASP网站程序的设计
  • “一盘货卖全球”之后,天猫今年将推出国货“出海2.0版”
  • 分析图第一讲前期准备,渲染白模5.9
  • java如何获取SQL查询结果集中的行数和列数
  • 中小型企业到底需要什么样的ERP
  • 常见Filed Types
  • launcher 分析
  • 响应式一级到三级导航
  • 纯键盘开发实战(Mouseless Programming)
  • 关于spring和ibatis的整合
  • mybatis java.lang.NumberFormatException: For input string: D
  • 【译】JS基础算法脚本:字符串结尾
  • 「前端」从UglifyJSPlugin强制开启css压缩探究webpack插件运行机制
  • bootstrap创建登录注册页面
  • flutter的key在widget list的作用以及必要性
  • HomeBrew常规使用教程
  • JAVA SE 6 GC调优笔记
  • JavaScript 无符号位移运算符 三个大于号 的使用方法
  • Javascript编码规范
  • JS基础篇--通过JS生成由字母与数字组合的随机字符串
  • LeetCode29.两数相除 JavaScript
  • mysql 数据库四种事务隔离级别
  • MySQL数据库运维之数据恢复
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • Webpack4 学习笔记 - 01:webpack的安装和简单配置
  • 闭包--闭包作用之保存(一)
  • 记一次和乔布斯合作最难忘的经历
  • 简单实现一个textarea自适应高度
  • 如何选择开源的机器学习框架?
  • 什么软件可以提取视频中的音频制作成手机铃声
  • RDS-Mysql 物理备份恢复到本地数据库上
  • 阿里云ACE认证之理解CDN技术
  • #stm32驱动外设模块总结w5500模块
  • #调用传感器数据_Flink使用函数之监控传感器温度上升提醒
  • (4.10~4.16)
  • (顶刊)一个基于分类代理模型的超多目标优化算法
  • (二)学习JVM —— 垃圾回收机制
  • (附源码)spring boot校园健康监测管理系统 毕业设计 151047
  • (循环依赖问题)学习spring的第九天
  • (转)winform之ListView
  • .MSSQLSERVER 导入导出 命令集--堪称经典,值得借鉴!
  • .MyFile@waifu.club.wis.mkp勒索病毒数据怎么处理|数据解密恢复
  • .NET Core 将实体类转换为 SQL(ORM 映射)
  • .NET Framework与.NET Framework SDK有什么不同?
  • .net 调用php,php 调用.net com组件 --
  • .net2005怎么读string形的xml,不是xml文件。
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NET上SQLite的连接
  • .Net下使用 Geb.Video.FFMPEG 操作视频文件
  • @RequestMapping用法详解
  • @RequestMapping-占位符映射