javascript的this关键字详解
作者:iceberg_yao 发布时间:2024-04-17 10:08:44
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 的过程中会发生以下流程
创建一个空对象,作为将要返回的对象实例
将该空对象的原型指向构造函数的 prototype 属性
将该空对象赋值给构造函数内部的 this 关键字
执行构造函数内部代码
默认返回 this 对象(如 return 的为非对象类型,如数字 123,会被忽略进而默认 return this 对象)
由以上逻辑可知道 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关键字的用法详解整合网站的支持!
来源:https://blog.csdn.net/iceberg_Yao/article/details/90299963
猜你喜欢
- 我确定有很多关于Unicode和Python的说明,但为了方便自己的理解使用,我还是打算再写一些关于它们的东西。 字节流 vs U
- SQLite是一款轻型的数据库,是遵守ACID的关系型数据库管理系统。不像常见的客户-服务器范例,SQLite引擎不是个程序与之通信的独立进
- 前言这是Go单元测试从入门到放弃系列教程的第1篇,介绍了如何使用httptest和gock工具进行网络测试。在上一篇《Go单元测试从入门到放
- 在多个文件或者不同语言协同的项目中,python脚本经常需要从命令行直接读取参数。万能的python就自带了argprase包使得这一工作变
- 说明本文根据https://github.com/liuchengxu/blockchain-tutorial的内容,用python实现的,
- 前言Python 3.7 将于今年夏天发布,Python 3.7 中将会有许多新东西:各种字符集的改进对注释的推迟评估以及对dataclas
- 关于Python 黑魔法 metaclass 的两种极端观点:这种特性太牛逼了,是无所不能的阿拉丁神灯,必须找机会用上才能显示自己的 Pyt
- Python的集合set原理集合(set)是一个无序的不重复元素序列。可以使用大括号 { } 或者 set() 函数创建集合,注意:创建一个
- python字符串查找函数的使用打开Python开发工具IDLE,新建‘findstr.py'文件,并写代码如下:s ='/
- 前言最近在学习微信小程序,在学习的过程中,有很多好玩的 API,经常点外卖的同学可能在小程序中遇到过,比如:某团、某了么都是有显示当前用户位
- 开门见山自动化测试过程中,一般测试结果都会以邮件的形式发送给相关人员,那么,在Python中,如何编写代码将邮件发送给对应的用户?同时,发送
- 前言嗨,彦祖们,不会过圣诞了还是一个人吧?今天我们来讲一下如何用python来画一个圣诞树,学会就快给那个她发过去吧,我的朋友圈已经让圣诞树
- 目录前言1. 准备工作2. 连接MongoDB3. 指定数据库4. 指定集合5. 插入数据6. 查询7. 计数8. 排序9. 偏移10. 更
- 本文实例讲述了Python基于递归算法求最小公倍数和最大公约数。分享给大家供大家参考,具体如下:# 最小公倍数def lcm(a, b, c
- 如下所示:#!/usr/bin/env python#_*_ coding:utf-8 _*_name = ['hello'
- 什么是WebAPIWebAPI就是 DOM API + BOM APIDOMW3C标准给我们提供了一系列的函数,让我们可以操作:网页内容、网
- 在SQL语句优化过程中,我们经常会用到hint,现总结一下在SQL优化过程中常见Oracle HINT的用法:1. /*+ALL_ROWS*
- 1 configparser安装pip3 install configparser2 configparser简介用来读取配置文件的pyth
- 因此为了节省服务器资源,应该尽可能关闭连接以释放连接所占有的资源,这种关闭记录集的连接而不关闭记录集的技术叫做断开记录集,这个记录集本身则称
- 本文实例讲述了JS实现简单的抽奖转盘效果。分享给大家供大家参考,具体如下:<!DOCTYPE html><html lan