再次谈论Javascript中的this


Posted in Javascript onJune 23, 2016

 一直对Javascript中的this都有一种似是而非的感觉,今天突然感觉豁然开朗,特此记录一下。

咱们先看个栗子:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this的使用</title>
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
var carKey=document.getElementById('car_key');
carKey.onclick=function () {
this.start(); 
};
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</head>
<body>
<input type="button" id="car_key" value="test" />
</body>
</html>

咋一看这段代码没有什么问题,但是由于对于this的错误理解最终导致错误的结果。我们在元素car_key上面绑定了click事件,认为在car的类中嵌套绑定click事件就可以让这个dom元素访问car的this上下文。这种方式看起来很合理,但是不幸的是它并不工作。

在Javascript中,this关键字总是指向正执行的作用域的所有者。

请大家仔细揣摩上面那句话。正如我们所知,函数调用会产生新的作用域,一点onclick事件被触发,this就指向了dom元素而不是Car的类。

那我们怎么做才会让它能正常工作呢?我们通常会把this赋值给一个局部的自由变量(比如that,_this,self,me等,这个在许多的框架里面都有体现)来避开作用域带来的问题。这里使用局部变量来重写之前的方法:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this的使用</title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
var that=this;
var carKey=document.getElementById('car_key');
carKey.onclick=function () {
that.start(); 
};
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html>

由于that是一个自由变量,onclick事件的出发并不会引起它的重新定义。

  如果你熟悉ES6的话可以使用胖箭头符号,这更简洁和更容易理解,如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this的使用</title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
this.turnKye=function () {
//var that=this;
var carKey=document.getElementById('car_key');
//carKey.onclick=function () {
// that.start(); 
//};
carKey.onclick=()=>this.start();
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html>

当然我们也可以使用绑定函数的方法来解决这个问题:如下

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>this的使用</title>
</head>
<body>
<input type="button" id="car_key" value="test" />
<script type="text/javascript">
var Car,tesla;
Car=function () {
this.start=function(){
console.log('car started');
};
var click=function(){
this.start(); 
}
this.turnKye=function () {
//var that=this;
var carKey=document.getElementById('car_key');
carKey.onclick=click.bind(this);
}
return this;
}
tesla=new Car();
tesla.turnKye();
</script>
</body>
</html>

其实这些在学习React的时候,绑定事件的时候遇到的坑,那时候只知道这么写,不知道怎么回事,今天突然感觉豁然开朗。希望对大家有所帮助。

Javascript 相关文章推荐
IE JS无提示关闭窗口不提示的方法
Apr 29 Javascript
基于jquery的让textarea自适应高度的插件
Aug 03 Javascript
javascript实现漂亮的拖动层,窗口拖拽特效
Apr 24 Javascript
BootStrap使用popover插件实现鼠标经过显示并保持显示框
Jun 23 Javascript
JS判断两个对象内容是否相等的方法示例
Apr 10 Javascript
原生js获取left值和top值的三种方法
Aug 02 Javascript
js链表操作(实例讲解)
Aug 29 Javascript
vue.js或js实现中文A-Z排序的方法
Mar 08 Javascript
JS关闭子窗口并且刷新上一个窗口的实现示例
Mar 10 Javascript
从表单校验看JavaScript策略模式的使用详解
Oct 17 Javascript
微信小程序实现页面左右滑动
Nov 16 Javascript
vue中的可拖拽宽度div的实现示例
Apr 08 Vue.js
BootStrap使用popover插件实现鼠标经过显示并保持显示框
Jun 23 #Javascript
Bootstrap导航条可点击和鼠标悬停显示下拉菜单的实现代码
Jun 23 #Javascript
Bootstrap弹出带合法性检查的登录框实例代码【推荐】
Jun 23 #Javascript
JS留言功能的简单实现案例(推荐)
Jun 23 #Javascript
Bootstrap实现登录校验表单(带验证码)
Jun 23 #Javascript
JavaScript自学笔记(必看篇)
Jun 23 #Javascript
Bootstrap中文本框的宽度变窄并且加入一副验证码图片的实现方法
Jun 23 #Javascript
You might like
编写安全 PHP应用程序的七个习惯深入分析
2013/06/08 PHP
PHP连接MySQL数据的操作要点
2015/03/20 PHP
php实现爬取和分析知乎用户数据
2016/01/26 PHP
PHP的swoole扩展安装方法详细教程
2016/05/18 PHP
使用SyntaxHighlighter实现HTML高亮显示代码的方法
2010/02/04 Javascript
javascript中的=等号个数问题两个跟三个有什么区别
2013/10/23 Javascript
jQuery jcrop插件截图使用方法
2013/11/20 Javascript
用js提交表单解决一个页面有多个提交按钮的问题
2014/09/01 Javascript
javascript将中国数字格式转换成欧式数字格式的简单实例
2016/08/02 Javascript
JavaScript实现反转字符串的方法详解
2017/04/27 Javascript
深入理解vue $refs的基本用法
2017/07/13 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
2017/09/19 Javascript
微信小程序 页面滑动事件的实例详解
2017/10/12 Javascript
Mac中安装nvm的教程分享
2017/12/11 Javascript
Vue用mixin合并重复代码的实现
2020/11/27 Vue.js
[44:51]2018DOTA2亚洲邀请赛 4.4 淘汰赛 VP vs Liquid 第二场
2018/04/05 DOTA
python实现模拟按键,自动翻页看u17漫画
2015/03/17 Python
python获取指定路径下所有指定后缀文件的方法
2015/05/26 Python
python妙用之编码的转换详解
2017/04/21 Python
Python基于回溯法子集树模板解决选排问题示例
2017/09/07 Python
使用tensorflow显示pb模型的所有网络结点方式
2020/01/23 Python
翻转数列python实现,求前n项和,并能输出整个数列的案例
2020/05/03 Python
pandas dataframe 中的explode函数用法详解
2020/05/18 Python
python3.7+selenium模拟淘宝登录功能的实现
2020/05/26 Python
python3中celery异步框架简单使用+守护进程方式启动
2021/01/20 Python
浅析与CSS3的loading动画加载相关的transition优化
2015/05/18 HTML / CSS
船餐厅和泰晤士河餐饮游轮:Bateaux London
2018/03/19 全球购物
英国演唱会订票网站:Ticket Selection
2018/03/27 全球购物
Under Armour安德玛法国官网:美国高端运动科技品牌
2018/06/29 全球购物
PHP面试题-$message和$$message的区别
2015/12/08 面试题
SQL Server面试题
2013/04/04 面试题
奶茶专卖店创业计划书
2014/01/18 职场文书
大三学习计划书范文
2014/05/02 职场文书
爱的承诺书
2015/01/20 职场文书
护士自荐信怎么写
2015/03/06 职场文书
学校世界艾滋病日宣传活动总结
2015/05/05 职场文书