JavaScript中的this总是让人迷惑,应该是js众所周知的坑之一。 个人也觉得js中的this不是一个好的设计,由于this晚绑定的特性,它可以是全局对象,当前对象,或者…有人甚至因为坑大而不用this。

  其实如果完全掌握了this的工作原理,自然就不会走进这些坑。来看下以下这些情况中的this分别会指向什么:

  1.全局代码中的this

1
alert(this)//window

  全局范围内的this将会指向全局对象,在浏览器中即使window。

  2.作为单纯的函数调用

1
2
3
4
5
function fooCoder(x) {
    this.x = x;
}
fooCoder(2);
alert(x);// 全局变量x值为2

  这里this指向了全局对象,即window。在严格模式中,则是undefined。

  3.作为对象的方法调用

1
2
3
4
5
6
7
8
var name = "clever coder";
var person = {
    name : "foocoder",
    hello : function(sth){
        console.log(this.name + " says " + sth);
    }
}
person.hello("hello world");

  输出 foocoder says hello world。this指向person对象,即当前对象。

  4.作为构造函数

1
new FooCoder();

  函数内部的this指向新创建的对象。

  5.内部函数

1
2
3
4
5
6
7
8
9
10
11
var name = "clever coder";
var person = {
    name : "foocoder",
    hello : function(sth){
        var sayhello = function(sth) {
            console.log(this.name + " says " + sth);
        };
        sayhello(sth);
    }
}
person.hello("hello world");//clever coder says hello world

  在内部函数中,this没有按预想的绑定到外层函数对象上,而是绑定到了全局对象。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self:

1
2
3
4
5
6
7
8
9
10
11
12
var name = "clever coder";
var person = {
    name : "foocoder",
    hello : function(sth){
        var that = this;
        var sayhello = function(sth) {
            console.log(that.name + " says " + sth);
        };
        sayhello(sth);
    }
}
person.hello("hello world");//foocoder says hello world

  6.使用call和apply设置this

1
person.hello.call(person, "world");

  apply和call类似,只是后面的参数是通过一个数组传入,而不是分开传入。两者的方法定义:

1
2
call( thisArg [,arg1,arg2,… ] );  // 参数列表,arg1,arg2,...
apply(thisArg [,argArray] );     // 参数数组,argArray

  两者都是将某个函数绑定到某个具体对象上使用,自然此时的this会被显式的设置为第一个参数。

  简单地总结

  简单地总结以上几点,可以发现,其实只有第六点是让人疑惑的。

  其实就可以总结为以下几点:

  1.当函数作为对象的方法调用时,this指向该对象。

  2.当函数作为淡出函数调用时,this指向全局对象(严格模式时,为undefined)

  3.构造函数中的this指向新创建的对象

  4.嵌套函数中的this不会继承上层函数的this,如果需要,可以用一个变量保存上层函数的this。

  再总结的简单点,如果在函数中使用了this,只有在该函数直接被某对象调用时,该this才指向该对象。

1
2
3
obj.foocoder();
foocoder.call(obj, ...);
foocoder.apply(obj, …);

  更进一步

  我们可能经常会写这样的代码:

1
$("#some-ele").click = obj.handler;

  如果在handler中用了this,this会绑定在obj上么?显然不是,赋值以后,函数是在回调中执行的,this会绑定到$(“#some-div”)元素上。这就需要理解函数的执行环境。本文不打算长篇赘述函数的执行环境,可以参考《JavaScript高级程序设计》中对执行环境和作用域链的相关介绍。这里要指出的时,理解js函数的执行环境,会更好地理解this。

  那我们如何能解决回调函数绑定的问题?ES5中引入了一个新的方法,bind():

1
2
3
4
5
6
fun.bind(thisArg[, arg1[, arg2[, ...]]])
thisArg
当绑定函数被调用时,该参数会作为原函数运行时的this指向.当使用new 操作符调用绑定函数时,该参数无效.
arg1, arg2, ...
当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数.

  该方法创建一个新函数,称为绑定函数,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.

  显然bind方法可以很好地解决上述问题。

1
2
$("#some-ele").click(person.hello.bind(person));
//相应元素被点击时,输出foocoder says hello world

  其实该方法也很容易模拟,我们看下Prototype.js中bind方法的源码:

1
2
3
4
5
6
7
Function.prototype.bind = function(){
  var fn = this, args = Array.prototype.slice.call(arguments), object = args.shift();
  return function(){
    return fn.apply(object,
      args.concat(Array.prototype.slice.call(arguments)));
  };
};

  明白了么?

  相信看完全文以后,this不再是坑~

转载于:https://www.cnblogs.com/xuan52rock/p/4537930.html

详解JavaScript中的this相关推荐

  1. 详解 javascript中offsetleft属性的用法(转)

    详解 javascript中offsetleft属性的用法 转载  2015-11-11   投稿:mrr    我要评论 本章节通过代码实例介绍一下offsetleft属性的用法,需要的朋友可以做一 ...

  2. 前端中unescape是什么意思_详解JavaScript中的Unescape()和String() 函数

    JavaScript中的Unescape()和String() 函数详解,具体内容如下所示: 定义和用法 JavaScript unescape() 函数可对通过 escape() 编码的字符串进行解 ...

  3. 详解Javascript中的Object对象

    本文地址:http://luopq.com/2016/02/28/Object-in-Javascript/,转载请注明 Object是在javascript中一个被我们经常使用的类型,而且JS中的所 ...

  4. 科普向--详解JavaScript中的数据类型

    对于前端的小伙伴而言,JS的数据类型可谓是必懂的知识点.虽然这个知识点很是基础了,不过仍然有不少人会在这一块犯些小错误.比如网上流传的"JavaScriptS一切皆对象",其实是个 ...

  5. 详解JavaScript中void语句的使用

    void是在JavaScript中的一个重要的关键字可被用作其单操作数之前出现一元运算符,其可以是任何类型. 此运算符指定不需要返回值,进行计算的表达式.它的语法可能是下列之一: <script ...

  6. 详解Javascript中的Array对象

    本文地址:http://luopq.com/2016/04/01/Array-in-Javascript/,转载请注明 在上一篇文章中,我们详细介绍了Object对象.在这一篇文章中,我们来说说Arr ...

  7. 详解Javascript中正则表达式的使用

    章节目录 Javascript中正则表达式的使用 String.prototype.search方法 String.prototype.replace方法 String.prototype.split ...

  8. 【JavaScript】详解JavaScript中的replace()函数

    replace 1. 方法简介 2. replace()使用 2.1 replace(字符串,字符串) 2.2 replace(正则表达式,字符串) 2.3 replace(正则表达式,functio ...

  9. 服务器客户端消息设计,详解JavaScript中的客户端消息框架设计原理

    哇--是个危险的题目,对吗?我们对于什么是本质的理解当然会随着我们对要解决问题的理解而变化.因此我不会说谎--一年前我所理解的本质很不幸并不完整,因为我确信我将要写的已经快伴随我有6个月之久.所以,这 ...

最新文章

  1. java中mypoiexception,java - 如何使用Poi获取Java中单元格的数据验证源? - 堆栈内存溢出...
  2. freebsd mysql删_FreeBSD 下 mysql 的相关问题
  3. 图解weblogic安装
  4. 全球及中国民办教育行业规模预测与发展对策建议报告2022版
  5. 【转】!Dynamics 365 Online通过OAuth 2 Client Credential授权(Server-to-Server Authentication)后调用Web API
  6. 清空运行中的jar 日志_Java日志体系权威总结
  7. 纸上谈兵: 最短路径与贪婪
  8. debounce函数的实现
  9. Android studio打包遇到的问题总结
  10. 饥荒服务器地图配置文件,饥荒联机版世界地图设置心得 联机全地图设置方法...
  11. 【tcp】网络连接中的长连接和短连接是什么意思?
  12. PyTorch实现TPU版本CNN模型
  13. ATX电源故障导致某些主板不能启动
  14. ORACLE EBS常用表及查询语句(二)
  15. 稳定性和高可用如何保障?一手测评华为云网站高可用解决方案
  16. 不谈五险一金,难道要和你谈情怀吗?
  17. 直通车的转化怎样引流-纽黑文教学
  18. properties配置文件中 不能输入中文
  19. 基于易语言写QQ音乐播放器
  20. collect的几种形式_Java中的collection集合类型总结

热门文章

  1. jquery实现点击浏览器后退,上一页面自动刷新
  2. 全网最细节的sds讲解,轻松拿下offer
  3. Oracle-SQL语法基础【以一个完整项目为例】
  4. python【蓝桥杯vip练习题库】ALGO-141 P1102(学生信息)
  5. 数据拟合matlab算法
  6. 第四次人口普查数据_第七次人口普查预估:单身男性比女性多3000万?你在其中吗?...
  7. python functools.reduce_Python-functools模块(reduce、partial、lru_cache)
  8. 湖南网络推广教大家如何“挽回”网站被降权的排名和权重?
  9. 网站推广专员浅析不做大幅修改如何调整网站推广内容?
  10. 企业网络推广浅析外包企业网络推广如何有效布局关键词优化?