浅析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 ...
随机推荐
- openNebula 模板实例化成虚拟机【参数名为VM_NAME】
{ "action": { "perform": "instantiate", "params": { "vm ...
- Julien Nioche谈Apache Nutch 2的特性及产品路线图
原文地址: http://www.infoq.com/cn/articles/nioche-apache-nutch2 开源的Web搜索框架Apache Nutch的2.1版本已于2012年10月5日 ...
- IE6下z-index失效
一.匆匆带过的概念关于CSS中层级z-index的定义啊什么的不是本文的重点,不会花费过多篇幅详细讲述.这里就简单带过,z-index伴随着层的概念产生的.网页 中,层的概念与photoshop或是f ...
- C++ foreach
考虑下面的需求,对vector<int>中的每个元素加1,如何做? void add(int& lhs) // 注意:要修改主调方法中的数据,这里要使用引用 { lhs= lhs ...
- 0c-41-ARC使用特点及注意事项
1.ARC特点总结 1)不允许调用release,retain,retainCount 2)允许重写dealloc,但是不允许调用[super dealloc] 3)@property的参数: str ...
- vm内核参数优化设置
http://www.cnblogs.com/wjoyxt/archive/2014/06/08/3777042.html (1)vm.overcommit_memory 执行grep -i com ...
- DQS安装失败——系统重新引导是否处于挂起状态
问题: 安装完SQL Server 2012后,准备安装DQS服务,但是总是提示:操作"检查系统重新引导是否处于挂起状态"已完成,但有错误,正在中止安装.非常无奈, ...
- 文件共享windows server 2008 服务器
1.远程连接到windows server2008 E盘右键共享 2.不能创建文件夹 右键E盘→共享→高级共享→权限→全部打勾即可. 3.ok,文件服务器
- c++ 设计模式7 (Bridge 桥模式)
4.2 Bridge 桥模式 动机: 由于某些类型的固有的实现逻辑,使得它们具有两个变化的维度,乃至多个变化的维度. 代码示例: 实现一个Messager,含有基本功能PlaySound,Connec ...
- http协议学习(一)http状态
整理了一个脑图,算作是<图解HTTP>的读书笔记,这本书有很多插图,适合初学者入门理解. 讲解网络协议的书不多 其中两本被人们奉为圣经 <TCP/IP详解 卷一> <H ...