JavaScript中this详解
摘要:JavaScript中的this总是让人迷惑,应该是js众所周知的坑之一。 个人也觉得js中的this不是一个好的设计,由于this晚绑定的特性,它可以是全局对象,当前对象,或者…有人甚至因为坑大而不用this。
其实如果完全掌握了this的工作原理,自然就不会走进这些坑。来看下以下这些情况中的this分别会指向什么:
1.全局代码中的this
- alert(x);// 全局变量x值为2
全局范围内的this将会指向全局对象,在浏览器中即使window。
2.作为单纯的函数调用
- function fooCoder(x) {
- this.x = x;
- }
- fooCoder(2);
- alert(x);// 全局变量x值为2
这里this指向了全局对象,即window。在严格模式中,则是undefined。
3.作为对象的方法调用
- 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.作为构造函数
- new FooCoder();
函数内部的this指向新创建的对象。
5.内部函数
- var name = "clever coder";
- var person = {
- name : "foocoder",
- hello : function(sth){
- var sayhello = function(sth) {
- console.log(this.name + " says " + sth);
- };
- sayhello(
- }
- person.hello("hello world");//clever coder says hello world
在内部函数中,this没有按预想的绑定到外层函数对象上,而是绑定到了全局对象。这里普遍被认为是JavaScript语言的设计错误,因为没有人想让内部函数中的this指向全局对象。一般的处理方式是将this作为变量保存下来,一般约定为that或者self:
- 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
- person.hello.call(person, "world");
apply和call类似,只是后面的参数是通过一个数组传入,而不是分开传入。两者的方法定义:
- call( thisArg [,arg1,arg2,… ] ); // 参数列表,arg1,arg2,...
- apply(thisArg [,argArray] ); // 参数数组,argArray
两者都是将某个函数绑定到某个具体对象上使用,自然此时的this会被显式的设置为第一个参数。
简单地总结
简单地总结以上几点,可以发现,其实只有第六点是让人疑惑的。
其实就可以总结为以下几点:
- 当函数作为对象的方法调用时,this指向该对象。
- 当函数作为淡出函数调用时,this指向全局对象(严格模式时,为undefined)
- 构造函数中的this指向新创建的对象
- 嵌套函数中的this不会继承上层函数的this,如果需要,可以用一个变量保存上层函数的this。
再总结的简单点,如果在函数中使用了this,只有在该函数直接被某对象调用时,该this才指向该对象。
- obj.foocoder();
- foocoder.call(obj, ...);
- foocoder.apply(obj, …);
更进一步
我们可能经常会写这样的代码:
- $("#some-ele").click = obj.handler;
如果在handler中用了this,this会绑定在obj上么?显然不是,赋值以后,函数是在回调中执行的,this会绑定到$(“#some-div”)元素上。这就需要理解函数的执行环境。本文不打算长篇赘述函数的执行环境,可以参考《javascript高级程序设计》中对执行环境和作用域链的相关介绍。这里要指出的时,理解js函数的执行环境,会更好地理解this。
那我们如何能解决回调函数绑定的问题?ES5中引入了一个新的方法,bind():
- fun.bind(thisArg[, arg1[, arg2[, ...]]])
- thisArg
当绑定函数被调用时,该参数会作为原函数运行时的this指向.当使用new 操作符调用绑定函数时,该参数无效.
- arg1, arg2, ...
当绑定函数被调用时,这些参数加上绑定函数本身的参数会按照顺序作为原函数运行时的参数.
该方法创建一个新函数,称为绑定函数,绑定函数会以创建它时传入bind方法的第一个参数作为this,传入bind方法的第二个以及以后的参数加上绑定函数运行时本身的参数按照顺序作为原函数的参数来调用原函数.
显然bind方法可以很好地解决上述问题。
- $("#some-ele").click(person.hello.bind(person));
- //相应元素被点击时,输出foocoder says hello world
其实该方法也很容易模拟,我们看下Prototype.js中bind方法的源码:
- 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/kefeiGame/p/7661988.html
JavaScript中this详解相关推荐
- javascript中function详解
目录 概念 定义 函数内部 this arguments 绑定函数作用域 Function.prototype.bind Function.prototype.applay Function.prot ...
- JavaScript中作用域详解
1.作用域 作用域,即变量(变量作用域又称上下文)和函数生效(能被访问)的区域或集合 换句话说,作用域决定了代码区块中变量和其他资源的可见性 举个例子 function fn(){var info=' ...
- JavaScript中undefined详解
目录 一.前言 二.undefined的特点 1.undefined既是JavaScript中的原始数据类型之一,也是一个原始值数据 2.undefined是全局对象上的一个属性 3.undefine ...
- javaScript中Promise详解
ES2015正式发布(也就是ES6,ES6是它的乳名),其中Promise被列为正式规范.作为ES6中最重要的特性之一,我们有必要掌握并理解透彻.本文将由浅到深,讲解Promise的基本概念与使用方法 ...
- JavaScript中正则表达式详解
正则表达式的介绍 * 正则表达式也叫规则表达式[Regular Expression],是按照一定的规则组成的一个表达式,主要作用是用来匹配字符串的* 正则表达式可以在大多数编程语言中使用* 正则表达 ...
- javascript中逗号详解
逗号运算符 它将先计算左边的参数,再计算右边的参数值.然后返回最右边参数的值. var a = 3,b = 4;console.log((function(){ return b = 5,b })() ...
- 在HTML文档中使用JavaScript的方法详解
在HTML文档中使用JavaScript的方法详解 本文详细介绍,在HTML文档(也称为HTML页面或网页)中使用JavaScript脚本代码的多种方法. 假设要用JS生成字符☆直角三角形 实现Jav ...
- javascript BOM对象详解
javascript BOM对象详解 目标:本章节将分为9点详细介绍有关BOM对象的知识点 1.什么是BOM 2.BOM的构成 3.顶级对象window 4.window对象常见事件(页面加载事件和体 ...
- JavaScript 运行机制详解(理解同步、异步和事件循环)
1.为什么JavaScript是单线程? JavaScript语言的一大特点就是单线程,也就是说,同一个时间只能做一件事.那么,为什么JavaScript不能有多个线程呢?这样能提高效率啊. Java ...
最新文章
- vanpopup 高度_解决VantUI popup 弹窗不弹出或无蒙层的问题
- 因为数据库正在使用,所以无法获得对数据库的独占访问权(转)
- 3D脚本 maxscript入门教程(6)
- 经典C语言程序100例之七三
- pdo mysql连接类_PHP PDO-MYSQL:如何在不同类之间使用数据库连接
- 图表中如何实现动态变更分类轴与系列值
- 一个简单的倒计时js插件
- Yaf引入oss sdk
- 需求调研报告模板_精准摸底,把握需求:名师工作室开展培训活动调研报告
- 虚拟机安装mac os x详细图文教程
- [QNX Hypervisor 2.2用户手册]8.5 vCPU和Hypervisor性能
- 超声波传感器for蓝桥杯
- Zedboard(一)开发环境Vivado
- 成都拓嘉启远:拼多多下单后地址错误能改吗
- UNCTF 2022 部分WP
- 通过裁切视频画面来改变视频尺寸 ,同时不影响画质
- (原創) 白蘋驚魂記 (iPhone)
- 电源系统优化设计,低压差稳压器(LDO)如何选型?
- zz:使用Monkeyrunner进行Android自动化的总结
- C++面向对象程序设计 024:这是什么鬼delete ---- (北大Mooc)