JavaScript中this用法学习笔记


Posted in Javascript onMarch 17, 2019

JavaScript这门语言中,最令人迷惑的地方有三个,闭包、this、原型。针对大多数人,可以利用词法作用域等避开this的坑,但是我们不能一直生活在舒适区,要敢于打破砂锅问到底,对我们来说也是一种提升。

一、一般对this关键字的误解:

1、this指向函数自身

2、this指向函数词法作用域

我们可以看以下一段代码:

function test() {
test.a = 1;
this.a = 2;
console.log(test.a);
console.log(this.a);
console.log(test.a === this.a);
}

test();
console.dir(test);

在上面这段代码中,我们在全局声明一个方法test,给test中的a属性赋值1,当前方法中的this中的a属性赋值2,加入this指向函数自身,那么test.a === this,a并且都等于2.

下面我们来看下这段代码的运行结果:

JavaScript中this用法学习笔记

JavaScript中this用法学习笔记

从上可以看出,scopes为全局作用域window,this也指向这里,虽然函数本身也是一个对象,但是this并不指向这里。

有一点我们一定要记住,this是在运行时进行绑定的,并不是在编写时绑定的,它的上下文取决于函数调用时的各种条件。this的绑定和函数声明的位置没有任何关系,只取决于函数的调用方式。

既然this是在运行时绑定的,那我们有没有办法改变当前this的绑定,使其不指向window,而指向方法test呢?答案是肯定的,我们可以借助一些强制绑定方法,如call、apply、bind来改变this的指向,我们可以将代码改成下面这种方式:

function test() {
 test.a = 1;
 this.a = 2;
 console.log(test.a);
 console.log(this.a);
 console.log(test.a === this.a);
 }
 
 test.call(test);
console.dir(test);

运行结果如下:

JavaScript中this用法学习笔记

JavaScript中this用法学习笔记

接下来我们看下this是否指向函数的词法作用域,以下有段比较有意思的代码:

function parent() {
 var a = 2;
 
 function child() {
 console.log(this.a)
 }
 child();
 
 }
parent();

假如this指向函数的词法作用域,那么child方法中的this.a应该是存在,实际上的执行结果如下:

JavaScript中this用法学习笔记

实际上,在JavaScript内部,作用域确实和对象类似,可见的标识符都是它的属性。但是作用域“对象”无法通过JavaScript代码访问,它存在JavaScript引擎内部。所以每当你想要把this和词法作用域的查找混合使用时,一定要提醒自己,这是无法实现的。

二、this的绑定规则

this的绑定规则大致分为以下几类:

2.1 默认绑定

2.2 隐式绑定

2.3 显式绑定

2.4 new绑定

2.1 默认绑定

上述示例中this的指向是指向window的,他们都有一个共同的特征,不带任何修饰的函数引用进行调用的,因此只能使用默认绑定,无法应用其他规则

2.2 隐式绑定

隐式绑定首先需要考虑的规则就是调用位置是否有上下文对象,或者说是否被某个对象拥有或包含,例如:

JavaScript中this用法学习笔记

这里的this就是指向对象obj。还有类似一些DOM事件的绑定,document.getElementById('xxx').addEventListener('click', function(){xxx});回调方法中的this是指向选择器选中的元素的。这种情况下可以简单的理解为this指向调用方法.前面的那个对象。

JavaScript中this用法学习笔记

2.3 显式绑定

显示绑定在开发过程中运用的比较多,借助于这些显式绑定方法,可以直接改变当前方法的this指向,使得js语言非常的灵活。主要有call、apply和bind三种,基本使用如下:

function sum() {
 console.log(this.a + this.b);
 }
 var obj1 = {
 a: 1,
 b: 2
 };
 var test = sum.bind(obj1);
 sum.call(obj1); //3
sum.apply(obj1); //3
test(); //3

注意事项:

call && apply第一个参数接受的是this对象,call第二个参数以后可以接受字符串形式的参数,apply接受的是一个类数组/数组参数

将null || undefined作为this的绑定对象传入call/apply/bind时,这些值在调用时会被忽略,实际应用的是默认绑定规则

2.4 new绑定

JavaScript语言中的new操作符和其他面向对象语言中的new操作符不大一样,因为在JavaScript中没有对象的概念。所有的函数都可以使用new来调用,new的调用又称为构造函数调用。在构造函数调用过程中,会自动执行下面的操作。

1、创建(或者说构造)一个全新的对象

2、这个对象会被执行[[Prototype]]连接

3、这个新对象会绑定到函数调用的this

4、如果函数没有返回其他对象,那么new表达式中的函数调用会自动返回这个新对象

构造函数也是js中常用的一种设计模式,如以下代码:

function Test(a, b) {
       this.a = a;
       this.b = b;
       this.add = function() {
         debugger;
        console.log(this.a + this.b);
       }
    }
    var cc = new Test(1, 2);
    cc.add();
    console.log(cc);

在new调用过程中,返回了一个新对象,并且该对象的this指向Test;

JavaScript中this用法学习笔记

Javascript 相关文章推荐
什么是DOM(Document Object Model)文档对象模型
Mar 05 Javascript
JavaScript判断按钮被点击的方法
Dec 13 Javascript
javascript每日必学之多态
Feb 23 Javascript
Bootstrap每天必学之模态框(Modal)插件
Apr 26 Javascript
JavaScript函数节流和函数防抖之间的区别
Feb 15 Javascript
React Component存在的几种形式详解
Nov 06 Javascript
发布一款npm包帮助理解npm的使用
Jan 03 Javascript
微信小程序实现页面跳转传递参数(实体,对象)
Aug 12 Javascript
element表格翻页第2页从1开始编号(后端从0开始分页)
Dec 10 Javascript
Vue.js实现立体计算器
Feb 22 Javascript
实例讲解React 组件
Jul 07 Javascript
vue.js页面加载执行created,mounted的先后顺序说明
Nov 07 Javascript
通过JavaScript下载文件到本地的方法(单文件)
Mar 17 #Javascript
微信小程序登录session的使用
Mar 17 #Javascript
Javascript读写cookie的实例源码
Mar 16 #Javascript
vue自定义键盘信息、监听数据变化的方法示例【基于vm.$watch】
Mar 16 #Javascript
vue自定义指令用法经典实例小结
Mar 16 #Javascript
简单易扩展可控性强的Jquery转盘抽奖程序
Mar 16 #jQuery
基于vue通用表单解决方案的思考与分析
Mar 16 #Javascript
You might like
微信公众平台消息接口校验与消息接口响应实例
2014/12/23 PHP
PHP封装函数实现生成随机的字符串验证码
2017/01/24 PHP
PHP实现的curl批量请求操作示例
2018/06/06 PHP
JS保留小数点(四舍五入、四舍六入)实现思路及实例
2013/04/25 Javascript
js判断浏览器类型的方法
2013/08/07 Javascript
JS不能跨域借助jquery获取IP地址的方法
2014/08/20 Javascript
多个js毫秒倒计时同时进行效果
2016/01/05 Javascript
浅谈JavaScript前端开发的MVC结构与MVVM结构
2016/06/03 Javascript
js运动事件函数详解
2016/10/21 Javascript
vue基于mint-ui实现城市选择三级联动
2020/06/30 Javascript
NodeJs 文件系统操作模块fs使用方法详解
2018/11/26 NodeJs
基于Bootstrap和JQuery实现动态打开和关闭tab页的实例代码
2019/06/10 jQuery
layui数据表格跨行自动合并的例子
2019/09/02 Javascript
详解关闭令人抓狂的ESlint 语法检测配置方法
2019/10/28 Javascript
微信小程序中网络请求缓存的解决方法
2019/12/29 Javascript
Vue实现浏览器打印功能的代码
2020/04/17 Javascript
javascript实现贪吃蛇游戏(娱乐版)
2020/08/17 Javascript
python批量导出导入MySQL用户的方法
2013/11/15 Python
python timestamp和datetime之间转换详解
2017/12/11 Python
python 通过麦克风录音 生成wav文件的方法
2019/01/09 Python
python matplotlib画盒图、子图解决坐标轴标签重叠的问题
2020/01/19 Python
python字符串,元组,列表,字典互转代码实例详解
2020/02/14 Python
美国汽配连锁巨头Pep Boys官网:轮胎更换、汽车维修服务和汽车零部件
2017/01/14 全球购物
波兰在线体育用品商店:Hop-Sport.pl
2019/07/23 全球购物
蒂娜商店:Tiina the Store
2019/12/07 全球购物
EJB2和EJB3在架构上的不同点
2014/09/29 面试题
什么是GWT的Entry Point
2013/08/16 面试题
文科教师毕业的自我评价
2014/01/16 职场文书
工伤事故处理协议书怎么写
2014/10/15 职场文书
资金申请报告范文
2015/05/14 职场文书
为什么说餐饮很难做,是因为你不了解这些新规则
2019/08/20 职场文书
nginx对http请求处理的各个阶段详析
2021/03/31 Servers
php7中停止php-fpm服务的方法详解
2021/05/09 PHP
PostgreSQL自动更新时间戳实例代码
2021/11/27 PostgreSQL
Python利用Turtle绘制哆啦A梦和小猪佩奇
2022/04/04 Python
java高级用法JNA强大的Memory和Pointer
2022/04/19 Java/Android