this的五种指法
this 到底指向哪里
以下如果没提及,则为严格模式。
js中作用域有两种:
- 词法作用域
- 动态作用域
词法作用域
词法作用域指在书写代码时就被确定的作用域。
看如下代码
var value = 1;
function foo() {
console.log(value);
}
function bar() {
var value = 2;
foo();
}
bar();// 结果是1
动态作用域
动态作用域指在代码运行时才被确定的作用域。
js中只有this的作用域是动态作用域
this的五种绑定
初学js时,会想当然认为this遵循某一条规律,就像物理学那样,然而并不是。
this的绑定分为五种情况,这五种情况之间毫无规律可言。不过好在都很简单。
一. 默认绑定
当以如下形式执行一个函数时,this为默认绑定;
func()
- 严格模式下,this为undefined
- 非严格模式下,this是全局对象。
与函数调用嵌套多少层如何嵌套无关
/* 全是undefined */
function printThis(){
return this
}
var obj = {
say(){
console.log('obj.say',printThis())
}
}
function funcB(){
console.log('funcB',printThis());
obj.say();
}
console.log('funcA',printThis())
obj.say()
funcB()
二. 隐式绑定
当以如下行驶执行一个函数时,this为隐式绑定;
a.b.func()
此时this指向点前面一个对象
赋值会改变隐式绑定this的指向
- 方法赋值给变量
class T {
dotInvoke() {
console.log('dotInvoke', this.sayThis())
}
sayThis() {
return this
}
assignInvoke() {
var sayThis = this.sayThis;
console.log('assignInvoke', sayThis())
}
}
var tt = new T();
tt.dotInvoke()// 指向T
tt.assignInvoke()// undefined
- 函数被赋值成方法
function printThis(){
return this
}
var obj = {};
obj.say = printThis;
obj.say()/* 指向obj */
- 赋值给参数
极为常见的是回调函数的this是undefined,因为回调函数被复制给参数,参数再调用时变成了默认绑定
function asyncFun(cb){
cb()
}
var obj = {
callback(){
console.log(this)
}
}
obj.callback()/*隐式绑定 obj */
asyncFun(obj.callback);/*默认绑定 undefined */
三. 箭头函数
箭头函数会让this指向最近的函数或全局作用域
- 与最近的函数的this指向相同
function foo() {
// 返回一个箭头函数
return (a)=>{
//this 继承自 foo()
return this.a
}
;
}
var obj1 = {
a: 'obj1'
};
var obj2 = {
a: 'obj2'
}
var arrow1 = foo.call(obj1);
var arrow2 = foo.call(obj2);
var arrow3 = foo();
console.log('arrow1',arrow1())/* obj1 */
console.log('arrow2',arrow2())/* obj2 */
console.log('arrow3',arrow3())/* undefined,严格模式下报错 */
- 指向全局
var printThis = ()=>this;
console.log('printThis',printThis());/* global */
- 指向实例
class Test {
printThis = ()=>{
return this
}
}
//会被babel翻译成
var test = function test() {
var _this = this;
this.printThis = function () {
return _this;
};
};
四. 显示绑定
call, apply, bind指定this指向
五. new绑定
构造函数,ES6中的class
new构造函数,new class时,this指向实例
总结
- 五种绑定,后面两种情况单一,前面两种会因为方法,函数被赋值而互相转化。
- 因为this处于动态作用域,而目前开发时又大量使用框架。我们写下的代码,并不总是由我们自己调用,而是被打包工具打包后,由框架调用。导致我们并不知道我们写下的函数和方法是否被框架复制过或显示绑定过而改变了this指向。以至this指向更加扑朔迷离。
- 写完本文顿时觉得,python里指向明确的self完爆js的this。
来源:https://segmentfault.com/a/1190000017715350
this的五种指法的更多相关文章
- JavaScript常见的五种数组去重的方式
▓▓▓▓▓▓ 大致介绍 JavaScript的数组去重问题在许多面试中都会遇到,现在做个总结 先来建立一个数组 var arr = [1,2,3,3,2,'我','我',34,'我的',NaN,NaN ...
- Android之数据存储的五种方法
1.Android数据存储的五种方法 (1)SharedPreferences数据存储 详情介绍:http://www.cnblogs.com/zhangmiao14/p/6201900.html 优 ...
- 简述linux同步与异步、阻塞与非阻塞概念以及五种IO模型
1.概念剖析 相信很多从事linux后台开发工作的都接触过同步&异步.阻塞&非阻塞这样的概念,也相信都曾经产生过误解,比如认为同步就是阻塞.异步就是非阻塞,下面我们先剖析下这几个概念分 ...
- xmlHttp.readyState的五种状态
自己简单的总结一下 深入的了解可以看其他道友的 O(∩_∩)O readyState有五种可能的值: 0 (未初始化): (XMLHttpRequest)对象已经创建,但还没有调用open()方法. ...
- Redis五种数据结构简介
Redis五种结构 1.String 可以是字符串,整数或者浮点数,对整个字符串或者字符串中的一部分执行操作,对整个整数或者浮点执行自增(increment)或者自减(decrement)操作. 字符 ...
- Android中Button的五种监听事件
简单聊一下Android中Button的五种监听事件: 1.在布局文件中为button添加onClick属性,Activity实现其方法2.匿名内部类作为事件监听器类3.内部类作为监听器4.Activ ...
- 五种方式让你在java中读取properties文件内容不再是难题
一.背景 最近,在项目开发的过程中,遇到需要在properties文件中定义一些自定义的变量,以供java程序动态的读取,修改变量,不再需要修改代码的问题.就借此机会把Spring+SpringMVC ...
- php五种常见的设计模式(转载)
很多人都想着写博客来记录编程生活中的点滴,我也不例外,但想了好长时间不知道写什么........万事开头难,先转载一篇吧..... 设计模式 一书将设计模式引入软件社区,该书的作者是 Erich Ga ...
- Android_安卓为按钮控件绑定事件的五种方式
一.写在最前面 本次,来介绍一下安卓中为控件--Button绑定事件的五种方式. 二.具体的实现 第一种:直接绑定在Button控件上: 步骤1.在Button控件上设置android:onClick ...
随机推荐
- selenium基础(下拉菜单操作)
selenium基础(下拉菜单操作) 非select/option元素: 1.触发下拉列表出现 2.等待下拉列表中的元素出现,然后进行选择元素即可. select/option元素: 下拉框操作-Se ...
- QTableView的indexAt使用方法
要实现的功能是QTableview中Item项上右键弹出菜单这就必然要判断点击右键时鼠标指针是否在QTableView的Item上 如果是QTableWidget可以用itemAt来判断QTableV ...
- 《你不知道的JavaScript》上卷——第1章
知识点总结 1.什么是作用域? 作用域是根据名称查找变量的一套规则. 2.通常将JavaScript归类为“动态”或“解释执行”语言,但事实上它是一门编译语言. 3.编译 在传统编译语言的流程中,程序 ...
- 根据table返回来的数据,动态展示组织名称
<template> <div class="app-container calendar-list-container"> <el-card cla ...
- index方法用于数据集的强制索引操作
index方法为3.2.3版本新增,用于数据集的强制索引操作,例如: $Model->index('user')->select(); 对查询强制使用user索引,user必须是数据表实际 ...
- hdu 5382
\(F(n)=\sum_{i=1}^n\sum_{j=1}^n[lcm(i,j)+gcd(i,j)\geq n]\) \(S(n)=\sum_{i=1}^nF(i)\) \(F(n)=n^2-\sum ...
- 「题解」:07.18NOIP模拟赛T1:星际旅行
问题 A: 星际旅行 时间限制: 1 Sec 内存限制: 256 MB 题面 题面谢绝公开. 考试心路历程 拿到这道题感觉很懵逼,所以先搞的T2和T3,最后码了个暴力,结果还不如直接输出‘0’得分高 ...
- css3中 百分比宽度减去固定宽度的写法
div{ /*实现了宽度为父容器宽度减去固定的300像素*/ width:-webkit-calc(100% - 300px); width:-moz-calc(100% - 300px); widt ...
- Redis学习笔记01-分布式锁
1.分布式锁的定义与理解 在并发任务中,当对数据执行修改和删除时为了防止多个任务同时拿到数据而产生的混乱,这时就要用到分布式锁来限制程序的并发执行. Redis分布式锁本质上要实现的目标就是在Redi ...
- C#获取MP3,WMA信息
用于获取MP3内部信息,包括歌曲名,歌手名等…… namespace FileBatchRemaer.domain { /// <summary> /// Mp3信息结构 /// < ...