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权威指南第六版

晓婼:http://www.cnblogs.com/xiaoruo/p/4492453.html

浅析js中的this的更多相关文章

  1. 浅析JS中的模块规范(CommonJS,AMD,CMD)////////////////////////zzzzzz

    浅析JS中的模块规范(CommonJS,AMD,CMD)   如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已.     ...

  2. 浅析JS中的堆内存与栈内存

    最近跟着组里的大佬面试碰到这么一个问题, Q:说说var.let.const的区别 A:balabalabalabla... Q:const定义的值能改么? A:你逗我?不能吧 不知道各位看官怎么想? ...

  3. 浅析 JS 中的作用域链

    作用域链的形成 在 JS 中每个函数都有自己的执行环境,而每个执行环境都有一个与之对应的变量对象.例如: var a = 2 function fn () { var a = 1 console.lo ...

  4. 浅析JS中的模块规范(CommonJS,AMD,CMD)

    如果你听过js模块化这个东西,那么你就应该听过或CommonJS或AMD甚至是CMD这些规范咯,我也听过,但之前也真的是听听而已. 现在就看看吧,这些规范到底是啥东西,干嘛的. 一.CommonJS ...

  5. 浅析js中2个等号与3个等号的区别(转)

    首先,== equality 等同,=== identity 恒等. ==, 两边值类型不同的时候,要先进行类型转换,再比较. ===,不做类型转换,类型不同的一定不等. 下面分别说明: 先说 === ...

  6. 浅析JS中的模块规范AMD和CMD

    一.AMD AMD就只有一个接口:define(id?,dependencies?,factory); 它要在声明模块的时候制定所有的依赖(dep),并且还要当做形参传到factory中,像这样: d ...

  7. 浅析js中的堆和栈

    这里先说两个概念:1.堆(heap)2.栈(stack)堆 是堆内存的简称.栈 是栈内存的简称.说到堆栈,我们讲的就是内存的使用和分配了,没有寄存器的事,也没有硬盘的事.各种语言在处理堆栈的原理上都大 ...

  8. 浅析js中取绝对值的2种方法

    1.abs()   var aaa=-20;   var bbb=Math.abs(aaa); 2.加减法   var aaa=-20;   var bbb=-aaa

  9. 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 ...

随机推荐

  1. jQuery生成全页面的悬浮覆盖层效果(overlay)

    可能在大家开发的过程中,往往需要自己生成一个全页面的覆盖层,以便让用户能够把注意力专注于开发者指定的某一个区域,在这里开发小技巧里,我们使用非常简单的代码生成类似的效果,如下: $("#ov ...

  2. BZOJ 1014: [JSOI2008]火星人prefix Splay+二分

    1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...

  3. Codeforces Round #340 (Div. 2) D. Polyline 水题

    D. Polyline 题目连接: http://www.codeforces.com/contest/617/problem/D Descriptionww.co There are three p ...

  4. hdu 5594 ZYB's Prime 最大流

    ZYB's Prime Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5 ...

  5. linux C(undefined reference to `sqrt')

    那是因为没有链接到math库 可以这样来做,在后面加上-lm. 代码如下: gcc 10.c -o 10 -lm

  6. Android 实现自动接听和挂断电话功能

    添加权限 <uses-permission android:name="android.permission.CALL_PHONE"/> <uses-permis ...

  7. [Node.js] Broswerify -- 1

    Browserify is a tool that brings node.js style development to the browser. The thing you can see on ...

  8. java Servlet接口及应用

    基本类和接口 一.javax.servlet.Servlet接口 servlet抽象集是javax.servlet.Servlet接口,它规定了必须由Servlet类实现由servlet引擎识别和管理 ...

  9. LeetCode34 Search for a Range

    题目: Given a sorted array of integers, find the starting and ending position of a given target value. ...

  10. 短小实用 渗透用的Python小脚本

    渗透的很多时候,找到的工具并不适用,自己码代码才是王道,下面三个程序都是渗透时在网络上找不到合适工具,自己辛苦开发的,短小实用. 一.记录root密码小工具 root.py #!/usr/bin/py ...