浅析js中的this
this的用法
this在日常javascript编码中很常见, 但是一直以来没有好好总结过。 今天在这里好好总结一下。 本文只讨论浏览器环境。
this指向全局
var name = "window";
function foo() {
var name = "local";
console.log(this.name);
}
foo();
相信这段代码大家都看到过,在这里this指向了全局,输入结果是"window".一开始我也不理解为什么有些时候this是指向内部函数,有些时候是指向window了。 相信好多小伙伴都和我一样比较疑惑, 后来我去翻阅犀牛书,犀牛书对函数this的解释是:关键字this没有作业域限制, 嵌套的函数不会从调用它的函数中继承this如果函数嵌套作为方法调用其this的值指向调用它的对象。 如果嵌套函数作为函数调用,其this不是全局对象(非严格模式下)就是undefined(严格模式下)。
其实总结一下这段话就是: 一个函数如果是执行而不是作为一个对象的方法来使用,
那么它就指向全局对象或者undefined。 所以这就解释了第一段代码。
那接下来我们解释第二个结论:
作为对象的方法使用。
var name = "window";
function foo() {
var name = "local";
console.log(this.name);
}
var obj = {
name: 'local',
foo: foo
};
obj.foo();
根据上面的结果, 我们很容易得出这里的this就指向了对象obj。在一些称谓中,这个叫做this的隐式绑定。
call,apply 对this的显式绑定
个人不喜欢文字堆砌,还是直接上代码吧。
var name = "window";
var obj = {
name: "obj"
};
function foo() {
console.log(this.name);
}
foo(); //直接调用函数 this指向window
foo.call(obj); //改变函数的上下文,把obj传进去
这里显式绑定了函数的上下文,让this指向了obj,结果输入为“obj”
顺带提一下,call,apply的区别,面试题经常被问。
使用call或者apply让一个函数以一个对象的方法执行,第一个参数是指定上下文,可以是一个对象也可以是null。
call和apply区别是第二个参数,apply是数组的形式传参。
this在构造函数的使用
this的构造函数中使用蛮多的,也蛮方便的。
function Foo() {
this.a = "foo";
}
var f = new Foo();
console.log(f.a);
通过new一个函数,那么在构造函数中,this指向实例化的对象f。
上面说完了理论知识,那么我们来几个应用场景题
example 1:
var name = "window";
function foo() {
console.log(this.name);
}
var obj = {
name: 'obj',
foo: foo
};
var a = obj.foo;
a();
obj.foo = null;
a();
可能有些同学会认为function也是对象,对象的复制是引用类型复制,那么只是指向obj.foo,如果obj.foo置空了,那么a也就不能输出this.name了。其实结果不是的,函数的复制是值的复制,和数组复制造成引用或者其他的引用不一样。简单点说
a = obj.foo = function {
console.log(this.name);
}
那么,现在执行a(); 和obj里面的foo函数还没有任何关系了。既两次执行结果都是'window';
example 2:
看完上面这个例子,同样的我们有些是经常使用回调函数,把函数当一个参数传递,那这个参数是不是也是值的复制?请看下面的例子。
function aaa(fn) {
fn();
}
function foo() {
console.log(this.name);
}
var obj = {
name: 'obj',
foo: foo
};
aaa(obj.foo);
如果看不懂这个的话 ,这里也可以简化一下
function aaa(fn) { //在参数这里 可以理解为 var fn = obj.foo;
fn();
}
从例子1中我们可以知道函数是值的复制,那必然在aaa里面执行另外一个函数,而不是执行一个函数的方法,结果仍然是'window'.
example 3:
var name = "window";
setTimeout(function(){
var name = "local";
console.log(this.name);
},1000);
相信大家经常用定时器吧,那么有没有踩过这个坑,在定时器中,this是指向全局window的。
因为setTimeout是window下面的方法。代码可以转换为:
var name = "window";
window.setTimeout(function(){
var name = "local";
console.log(this.name);
},1000);
一个对象的方法使用,那内部的this是指向这个方法,必然this指向了这个对象本身,既window。
参考文档:
javascript权威指南第六版
浅析js中的this的更多相关文章
- 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz
浅析JS中的模块规范(CommonJS,AMD,CMD) 如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. ...
- 浅析JS中的堆内存与栈内存
最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...
- 浅析 JS 中的作用域链
作用域链的形成 在 JS 中每个函数都有自己的执行环境,而每个执行环境都有一个与之对应的变量对象.例如: var a = 2 function fn () { var a = 1 console.lo ...
- 浅析JS中的模块规范(CommonJS,AMD,CMD)
如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧,这些规范到底是啥东西,干嘛的. 一.CommonJS ...
- 浅析js中2个等号与3个等号的区别(转)
首先,== equality 等同,=== identity 恒等. ==, 两边值类型不同的时候,要先进行类型转换,再比较. ===,不做类型转换,类型不同的一定不等. 下面分别说明: 先说 === ...
- 浅析JS中的模块规范AMD和CMD
一.AMD AMD就只有一个接口:define(id?,dependencies?,factory); 它要在声明模块的时候制定所有的依赖(dep),并且还要当做形参传到factory中,像这样: d ...
- 浅析js中的堆和栈
这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...
- 浅析js中取绝对值的2种方法
1.abs() var aaa=-20; var bbb=Math.abs(aaa); 2.加减法 var aaa=-20; var bbb=-aaa
- JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别
JS中的 map, filter, some, every, forEach, for in, for of 用法总结和区别 :https://blog.csdn.net/hyupeng1006/a ...
随机推荐
- flume ng配置拓扑图
- Tomcat创建虚拟目录和程序热部署
虚拟目录的设置 方法一:在${tomcat安装目录}/conf/Catalina/localhost目录下添加与web应用同名的xml配置文件,这里站点名称为test为例子. test.xml内容:& ...
- Keil AGDI Header File
#ifndef __AGDI__INCED___ #define __AGDI__INCED___ //---Revision History: --------------------------- ...
- .NET连接SAP系统专题:C#调用RFC代码(三)
本文就说明在C#中如何编写代码来调用SAP中的RFC函数获取数据. 首先需要引用两个NCO3.0的DLL DLL下载地址:http://files.cnblogs.com/mengxin523/SAP ...
- C#如何通过NCO3.0来连接SAP并调用SAP中的RFC
,这是SAP针对.Net开发的专用组件,安装完成之后在C:\Program Files\SAP\SAP_DotNetConnector3_x86目录下面会有sapnco_utils.dll sapnc ...
- Class hierarchy of UIResponder as well as subclasses of UIView and UIControl
When you were dragging in your label and your button to this view, you were adding them as subviews. ...
- BZOJ 1053: [HAOI2007]反素数ant dfs
1053: [HAOI2007]反素数ant 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1053 Description 对于任何正整 ...
- Codeforces Round #189 (Div. 1) B. Psychos in a Line 单调队列
B. Psychos in a Line Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/problemset/p ...
- ip协议的数据分片备忘
总结: 不仅tcp协议能对数据段进行分割,ip协议也具备这个功能,之所以会这样是两者都受到底层MTU的限制(虽说tcp是根据MSS限制来分割数据包,由于MTU=tcp包头+ip包头+MSS,所以其实也 ...
- 疑难杂症:java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion(Ljava/lang/String;)V
错误: java.lang.AbstractMethodError: org.apache.xerces.dom.DocumentImpl.setXmlVersion(Ljava/lang/Strin ...