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关键字的用法详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]