javascript的this关键字详解


Posted in Javascript onMay 20, 2019

this 的定义

表示当前执行代码的环境对象

 因此可将 this 的剖析分为“全局环境” 和 “函数环境” 两种类型的环境对象

全局环境

console.log(this === window); // true
 
var a = 10;
console.log(this.a); // 10

函数环境

在函数内部,this 的取值取决于函数被调用时的运行环境。

这里涉及到内存里的数据结构相关的知识点,当我们定义以下字面量对象时会发生一系列的关联关系

var obj = { name: 'Tom' };

javascript 引擎会先在内存中生成 { name: 'Tom' } 对象,接着再把这个对象的内存地址赋值给 obj 变量,所以 obj 变量保存的只是一个内存地址而已,如果要获取 obj.name,javascript 引擎会先从 obj 变量中拿到内存地址,然后从该地址中获取原始对象,再返回 name 属性。

而属性值为函数时,该函数会被保存在内存中,然后将该内存地址赋值给该属性,因此该地址赋值给不同环境执行时它的作用域是不一样的,而 this 对象就是指向函数当前的执行环境对象,执行环境是会在 Event Loop(事件循环)过程中变化的,因此 this 在函数环境下是属于运行时的。

var name = 'Tom';
 
var obj = {
  name: 'Iceberg',
  say: function() {
    console.log('my name is ' + this.name);
  },
  sub: {
    say: function() {
      console.log('my name is ' + this.name);
    }
  }
};
 
obj.say(); // my name is Iceberg
obj.sub.say() // my name is undefined;
 
var say = obj.say;
say(); // my name is Tom;

上面的例子说明 obj.say() 执行环境为 obj 对象,而 obj.sub.say() 的执行环境却是 obj.sub 对象,而对于 obj.sub 来说并没有 name 属性,因此为 undefined;而 var say = obj.say; 则表示将 say 方法的内存地址赋值给全局变量,因此从全局变量 name 中取值。

运用场景

接下来从 this 在函数环境下的不同运用场景来剖析

事件回调函数

var handler = {
	nickname: 'anonymous',
	register: function() {
	  console.log(this.nickname);
	}	
}
 
$('#registerBtn').on('click', handler.register); // undefined

以上逻辑点击触发后输出的是 undefined,因为函数被当做事件触发的回调函数执行时,this 是指向该触发事件对应的元素,如要 this 仍然以 handler 对象为执行环境,则可使用函数的 bind 方法进行执行环境对象的绑定操作。

$('#registerBtn').on('click', handler.register.bind(handler)); // anonymous

在 react 中经常需要在回调函数中调用 this.state、this.props,按照上面的分析,将当前环境对象 bind 到回调函数中即可。

如果是使用的箭头函数定义回调函数即可无需 bind,因为箭头函数中 this 就是对应定义时所在的对象。
 构造函数

要理解 this 在构造函数中的逻辑就要理清楚构造函数在实例化过程中都发生了什么。

function A() {
  this.name = 'Tom';
  this.age = 20;
}
var a = new A();

使用 new 命令实例化构造函数 A 的过程中会发生以下流程

  1. 创建一个空对象,作为将要返回的对象实例
  2. 将该空对象的原型指向构造函数的 prototype 属性
  3. 将该空对象赋值给构造函数内部的 this 关键字
  4. 执行构造函数内部代码
  5. 默认返回 this 对象(如 return 的为非对象类型,如数字 123,会被忽略进而默认 return this 对象)
  6. 由以上逻辑可知道 this 关键字在构造函数中表示的是其实例对象。

bind

bind 方法将函数体中的 this 指向新对象并返回一个新函数

function A() {
  this.nickname = 'Tom';
  this.say = function() {
    console.log(this.nickname);
  }
}
var b = { nickname: 'John' };
var a = new A();
var say = a.say;
var say1 = a.say.bind(a);
var say2 = a.say.bind(b);
say(); // undefined
say1(); // Tom
say2(); // John

call & apply

call 方法是指 Function.prototype.call,因此每个函数都会具备 call 方法,fun.call(thisArg, arg1, arg2, ...),call 方法接收的第一个参数会替换原有的 this 指向的执行环境对象。

function A() {
  this.name = 'Tom';
  this.sayName = function(){
    console.log(this.name);
  };
}
 
function B() {
  this.name = 'John';
}
 
var a = new A();
a.sayName.call(new B()); // John

而 apply 方法与 call 的区别仅在于 call 接收参数列表而 apply 接收数组参数或者类数组对象(如函数的 arguments 对象)。

总结

由于 javascript 的 Event Loop 原理,决定了执行上下文会不断变化,因此 this 对象诞生于表达当前的执行环境对象。

以上所述是小编给大家介绍的javascript的this关键字的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!

Javascript 相关文章推荐
jquery的相对父元素和相对文档定位示例代码
Aug 02 Javascript
键盘KeyCode值列表汇总
Nov 26 Javascript
jQuery的animate函数实现图文切换动画效果
May 03 Javascript
jQuery动画效果图片轮播特效
Jan 12 Javascript
jQuery监听文件上传实现进度条效果的方法
Oct 16 Javascript
AngularJS实现路由实例
Feb 12 Javascript
Bootstrap BootstrapDialog使用详解
Feb 17 Javascript
vue-cli3脚手架的配置及使用教程
Aug 28 Javascript
layer插件实现在弹出层中弹出一警告提示并关闭弹出层的方法
Sep 24 Javascript
vue实现鼠标移过出现下拉二级菜单功能
Dec 12 Javascript
Bootstrap实现前端登录页面带验证码功能完整示例
Mar 26 Javascript
js不常见操作运算符总结
Nov 20 Javascript
小程序实现新用户判断并跳转激活的方法
May 20 #Javascript
node实现socket链接与GPRS进行通信的方法
May 20 #Javascript
JS求1到任意数之间的所有质数的方法详解
May 20 #Javascript
react 中父组件与子组件双向绑定问题
May 20 #Javascript
vue element-ui之怎么封装一个自己的组件的详解
May 20 #Javascript
一文搞懂ES6中的Map和Set
May 20 #Javascript
详解vue 在移动端体验上的优化解决方案
May 20 #Javascript
You might like
PHP缓存技术的使用说明
2011/08/06 PHP
php通过array_merge()函数合并两个数组的方法
2015/03/18 PHP
PHP创建文件,并向文件中写入数据,覆盖,追加的实现代码
2016/03/25 PHP
TP3.2框架分页相关实现方法分析
2020/06/03 PHP
JavaScript Event学习第三章 早期的事件处理程序
2010/02/07 Javascript
JavaScript 的继承
2011/10/01 Javascript
js常用代码段整理
2011/11/30 Javascript
js形成页面的一种遮罩效果实例代码
2014/01/04 Javascript
jquery 选取方法都有哪些
2014/05/18 Javascript
jQuery改变form表单的action,并进行提交的实现代码
2016/05/25 Javascript
利用jsonp跨域调用百度js实现搜索框智能提示
2016/08/24 Javascript
浅谈使用splice函数对数组中的元素进行删除时的注意事项
2016/12/04 Javascript
vue.js声明式渲染和条件与循环基础知识
2017/07/31 Javascript
原生js实现公告滚动效果
2021/01/10 Javascript
解决IOS端微信H5页面软键盘弹起后页面下方留白的问题
2019/06/05 Javascript
vue 动态设置img的src地址无效,npm run build 后找不到文件的解决
2020/07/26 Javascript
[02:27]2014DOTA2国际邀请赛 VG赛后采访:更大的挑战在等着我们
2014/07/13 DOTA
Python 获取新浪微博的最新公共微博实例分享
2014/07/03 Python
python实现mysql的读写分离及负载均衡
2018/02/04 Python
Python面向对象之接口、抽象类与多态详解
2018/08/27 Python
使用python对文件中的单词进行提取的方法示例
2018/12/21 Python
python-sys.stdout作为默认函数参数的实现
2020/02/21 Python
python 判断txt每行内容中是否包含子串并重新写入保存的实例
2020/03/12 Python
sklearn中的交叉验证的实现(Cross-Validation)
2021/02/22 Python
英国手工制作的现代与经典的沙发和床:Love Your Home
2020/09/26 全球购物
求两个数的乘积和商数,该作用由宏定义来实现
2013/03/13 面试题
Java中的异常处理机制的简单原理和应用
2013/04/27 面试题
市场部专员岗位职责
2013/11/30 职场文书
安全标准化汇报材料
2014/02/03 职场文书
小学老师对学生的评语
2014/12/29 职场文书
经典搞笑版检讨书
2015/02/19 职场文书
活动费用申请报告
2015/05/15 职场文书
《鸟的天堂》教学反思
2016/02/19 职场文书
《我们的民族小学》教学反思
2016/02/19 职场文书
2021-4-5课程——SQL Server查询【3】
2021/04/05 SQL Server
Java版 简易五子棋小游戏
2022/05/04 Java/Android