浅析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 ...
随机推荐
- Maven仓库的布局
任何一个构件都有其唯一的坐标,根据这个坐标可以定义其在仓库中的唯一存储路径,这便是Maven的仓库布局方式.例如log4j:log4j:1.2.15这一依赖,其对应的仓库路径为log4j/log4j/ ...
- Xen安全架构sHype/ACM策略配置图文教程
实验要求 1. 熟悉Xen虚拟化平台部署: 2. Xen sHype/ACM安全架构中的Simple TE和Chinese Wall策略及事实上现机制的分析与验证. 第1章 ...
- HDU 5578 Friendship of Frog 水题
Friendship of Frog Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.ph ...
- c#winform使用WebBrowser 大全[超长文转载]
1.主要用途:使用户可以在窗体中导航网页. 2.注意:WebBrowser 控件会占用大量资源.使用完该控件后一定要调用 Dispose 方法,以便确保及时释放所有资源.必须在附加事件的同一线程上调用 ...
- winForm 程序开发界面参数传递
1. using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; u ...
- Android 百度地图定位(手动+自动) 安卓开发教程
近由于项目需要,研究了下百度地图定位,他们提供的实例基本都是用监听器实现自动定位的.我想实现一种效果:当用户进入UI时,不定位,用户需要定位的时候,自己手动点击按钮,再去定位当前位置. 经过2天研究 ...
- 即时通信(RPC)的Rtmp实现--配置篇
http://flexman.blog.sohu.com/129838570.html http://flexman.blog.sohu.com/130007574.html step 1: 首先要确 ...
- poj - 2774 - Long Long Message
题意:输入2个长度不超过100000的字符串,问它们最长公共子串的长度. 题目链接:http://poj.org/problem?id=2774 ——>>后缀数组!后缀数组!-从LJ的&l ...
- 1028 - Carl the Ant
Ants leave small chemical trails on the ground in order to mark paths for other ants to follow. Ordi ...
- django schema migration
syncdb 仅仅能初始化table(create),不能自己主动update/delete/drop. 那么south应运而生. south简单使用方法: 安装: pip install South ...