JavaScript中的this关键字的几种用法
JS 里的 this
- 在 function 内部被创建
- 指向调用时所在函数所绑定的对象(拗口)
- this 不能被赋值,但可以被 call/apply 改变
1. this 和构造函数
function C(){
this.a = 37;
}
var o = new C();
console.log(o.a); // logs 37
function C2(){
this.a = 37;
return {a:38};
}
var b = new C2();
console.log(b.a); // logs 38
2. this 和对象
对象内部方法的this指向调用这些方法的对象:
- 函数的定义位置不影响其this指向,this指向只和调用函数的对象有关。
- 多层嵌套的对象,内部方法的this指向离被调用函数最近的对象(window也是对象,其内部对象调用方法的this指向内部对象, 而非window)。
//1:this指向调用函数的对象
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
console.log(o.f()); //37 this指向o
var a = o.f;
console.log(a()): //undefined this指向a ,a中没有定义prop
var o = {prop: 37};
function independent() {
return this.prop;
}
o.f = independent;
console.log(o.f()); // logs 37 this指向o
//2:this指向离被调用函数最近的对象
var o = {
prop: 37,
f: function() {
return this.prop;
}
};
function independent() {
return this.prop;
}
o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); //42 this指向o.b
3. this 和函数
普通函数内部的this分两种情况,严格模式和非严格模式。
//非严格模式下,this 默认指向全局对象window
function f1(){
return this;
}
f1() === window; // true
//而严格模式下, this为undefined
function f2(){
"use strict"; // 这里是严格模式
return this;
}
f2() === undefined; // true
4. 全局环境的this
前面提到 this 是 “指向调用时所在函数所绑定的对象”, 这句话拗口但绝对正确,没有一个多余的字。
全局环境中有不同的宿主对象,浏览器环境中是 window, node 环境中是 global。这里重点说下浏览器环境中的 this。
浏览器环境中非函数内 this 指向 window
alert(window=== this) // true
因此你会看很很多开源 JS lib 这么写
(function() {
// ...
})(this);
或这样写
(function() {
// ...
}).call(this);
比如 underscore 和 requirejs,大意是把全局变量 window 传入匿名函数内缓存起来,避免直接访问。至于为啥要缓存,这跟 JS 作用域链有关系,读取越外层的标识符性能会越差。
浏览器中比较坑人,非函数内直接使用 var 声明的变量默认为全局变量,且默认挂在 window 上作为属性。
var andy = '刘德华'
alert(andy === window.andy) // true
alert(andy === this.andy) // true
alert(window.andy === this.andy) // true
因为这个特性,有些笔试题如
var x = 10;
function func() {
alert(this.x)
}
var obj = {
x: 20,
fn: function() {
alert(this.x)
}
}
var fn = obj.fn
func() // 10
fn() // 10
没错,最终输出的都是全局的 10。永远记住这一点:
判断 this 指向谁,看执行时而非定义时,只要函数(function)没有绑定在对象上调用,它的 this 就是 window。
5. this和DOM事件
当函数被当做监听事件处理函数时, 其 this 指向触发该事件的元素 (针对于addEventListener事件)
// 被调用时,将关联的元素变成蓝色
function bluify(e){
//在控制台打印出所点击元素
console.log(this);
//阻止时间冒泡
e.stopPropagation();
//阻止元素的默认事件
e.preventDefault();
this.style.backgroundColor = '#A5D9F3';
}
// 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*');
// 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
for(var i=0 ; i<elements.length ; i++){
elements[i].addEventListener('click', bluify, false);
6. this和内联事件
内联事件中的this指向分两种情况:
- 当代码被内联处理函数调用时,它的this指向监听器所在的DOM元素
- 当代码被包括在函数内部执行时,其this指向等同于 函数直接调用的情况,即在非严格模式指向全局对象window, 在严格模式指向undefined



依次点击上边的三个按钮后在控制台的输出结果
7. setTimeout & setInterval
对于延时函数内部的回调函数的this指向全局对象window(当然我们可以通过bind方法改变其内部函数的this指向)
看下边代码及截图
//默认情况下代码
function Person() {
this.age = 0;
setTimeout(function() {
console.log(this);
}, 3000);
}
var p = new Person();//3秒后返回 window 对象
==============================================
//通过bind绑定
function Person() {
this.age = 0;
setTimeout((function() {
console.log(this);
}).bind(this), 3000);
}
var p = new Person();//3秒后返回构造函数新生成的对象 Person{...}


8. this可以被 call/apply 改变
当函数通过Function对象的原型中继承的方法 call() 和 apply() 方法调用时, 其函数内部的this值可绑定到 call() & apply() 方法指定的第一个对象上, 如果第一个参数不是对象,JavaScript内部会尝试将其转换成对象然后指向它。
例子:
function add(c, d){
return this.a + this.b + c + d;
}
var o = {a:1, b:3};
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34
function tt() {
console.log(this);
}
// 返回对象见下图(图1)
tt.call(5); // Number {[[PrimitiveValue]]: 5}
tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}

9. me/self/that/_this 暂存 this
如果采用 OOP 方式写 JS 代码,无可避免的会用到 this,方法内会访问类的内部属性(字段),也可能会调用类的另一个方法。当类的方法内又有一个 function 时,比如浏览器端开发经常遇见的给 DOM 元素添加事件,这时如果事件处理器(handler)中的想调用类的一个方法,此时 handler 内的 this 是 dom 元素而非类的当前对象。这个时候,需要把 this 暂存,开发者发挥着自己的聪明才智留下了几种经典的命名** me, self, that, _this**。如

如:

一般会在每个方法的第一句就把 this 暂存下来。
10. ES5 中新增的 bind 和 this
bind方法在ES5引入, 在Function的原型链上, Function.prototype.bind。通过bind方法绑定后, 函数将被永远绑定在其第一个参数对象上, 而无论其在什么情况下被调用。
function f(){
return this.a;
}
var g = f.bind({a:"azerty"});
console.log(g()); // azerty
var o = {a:37, f:f, g:g};
console.log(o.f(), o.g()); // 37, azerty
11. ES6 箭头函数=> 和 this
箭头函数的一个重要特征就是颠覆了上面的一句话,再贴一次
判断 this 指向谁,看执行时而非定义时,只要函数(function)没有绑定在对象上调用,它的 this 就是 window
是的,前面一直用这句话来判断 this 的指向,在箭头函数里前面半句就失效了。箭头函数的特征就是,定义在哪,this 就指向那。即箭头函数定义在一个对象里,那箭头函数里的 this 就指向该对象。如下
var book = {
author: 'John Resig',
init: function() {
document.onclick = ev => {
alert(this.author) ; // 这里的 this 不是 document 了
}
}
};
book.init()
对象 book 里有一个属性 author, 有一个 init 方法, 给 document 添加了一个点击事件,如果是传统的函数,我们知道 this 指向应该是 document,但箭头函数会指向当前对象 book。
箭头函数让 JS 回归自然和简单,函数定义在哪它 this 就指向哪,定义在对象里它指向该对象,定义在类的原型上,就指向该类的实例,望文知意这样更容易理解。
作为方法的箭头函数this指向全局window对象,而普通函数则指向调用它的对象
原文参考:
https://www.cnblogs.com/snandy/p/4773184.html
http://www.cnblogs.com/dongcanliang/p/7054176.html
JavaScript中的this关键字的几种用法的更多相关文章
- java 中的this关键字的几种用法
转自:http://blog.csdn.net/anmei2010/article/details/4091227 1. 当成员变量和局部变量重名时,在方法中使用this时,表示的是该方法所在 ...
- 如何理解JavaScript中的this关键字
前言 王福朋老师的 JavaScript原型和闭包系列 文章看了不下三遍了,最为一个初学者,每次看的时候都会有一种 "大彻大悟" 的感觉,而看完之后却总是一脸懵逼.原型与闭包 可以 ...
- 转载 深入理解JavaScript中的this关键字
转载原地址: http://www.cnblogs.com/rainman/archive/2009/05/03/1448392.html 深入理解JavaScript中的this关键字 1. 一 ...
- JavaScript中的this关键字的用法和注意点
JavaScript中的this关键字的用法和注意点 一.this关键字的用法 this一般用于指向对象(绑定对象); 01.在普通函数调用中,其内部的this指向全局对象(window); func ...
- 博文推荐】Javascript中bind、call、apply函数用法
[博文推荐]Javascript中bind.call.apply函数用法 2015-03-02 09:22 菜鸟浮出水 51CTO博客 字号:T | T 最近一直在用 js 写游戏服务器,我也接触 j ...
- JavaScript中常见的数组操作函数及用法
JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...
- JavaScript中常见的字符串操作函数及用法
JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...
- .NET(c#)new关键字的三种用法
前几天去家公司面试,有一道这样的题:写出c#中new关键字的三种用法,思前想后挖空心思也只想出了两种用法,回来查了下msdn,还真是有第三种用法:用于在泛型声明中约束可能用作类型参数的参数的类型,这是 ...
- NEW关键字的三种用法
最近面试中有一道题是写new关键字的几种用法,想了下写下我知道的两种用法 第一种 创建对象.调用构造函数,这就不用讲了 ClassA A=new ClassA(); 第二种 是作为修饰符,显示隐藏继 ...
随机推荐
- html如何设置表格单元格内容垂直居中?
父元素设置为表格的单元格元素td,而在表格单元格中的元素设置vertical-align: middle; 对父容器(td)使用:display: table-cell 其内子元素使用:vertica ...
- mysql中的字符集和校对规则(mysql校对集)
1.简要说明介绍 字符集和校对规则 字符集是一套符号和编码.校对规则是在字符集内用于比较字符的一套规则. MySql在collation提供较强的支持,oracel在这方面没查到相应的资料. 不同字符 ...
- PAT甲级——A1038 Recover the Smallest Number
Given a collection of number segments, you are supposed to recover the smallest number from them. Fo ...
- 通过游戏学python 3.6 第一季 第三章 实例项目 猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码 可复制直接使用 娱乐 可封装 函数
猜数字游戏--核心代码--猜测次数--随机函数和屏蔽错误代码 #猜数字--核心代码--猜测次数--随机函数和屏蔽错误代码 import random secrst = random.rand ...
- 手机前端开发调试利器-vConsole
最近因为做抽奖页面,在android上可以使用手机连上电脑后用chrome浏览器chrome://inspect进行页面探测,但是ios中的页面就不能这样探测 在网上搜索后发现此插件,大大解决了问题 ...
- ADO.NET实体数据模型
本文说一下如何使用ADO.NET实体数据模型,并解释一些概念. 1,首先你要建立一个数据库.比如我在SQL2005上面建立了数据库student,包含两个表: 2,然后再项目上添加新建项: 3,打开新 ...
- laravel-admin 自定义导出excel功能,并导出图片
https://www.jianshu.com/p/91975f66427d 最近用laravel-admin在做一个小项目,其中用到了excel导出功能. 但是laravel-admin自带的导出功 ...
- 笔记本最小安装centos7 连接WiFi的方法
1.首先下载iw工具. yum -y install iw 2.获取无线网卡的名称 执行iw dev,假设获得名称为 wlp3s0(示例) 3.激活无线网络接口 执行ip link set wlp3s ...
- ubuntu 12.4,搞定apt源
http://wiki.ubuntu.org.cn/Template:12.04source deb http://cn.archive.ubuntu.com/ubuntu/ precise main ...
- Ocelot(二)- 请求聚合
原文:Ocelot(二)- 请求聚合 Ocelot(二)- 请求聚合与负载均衡 作者:markjiang7m2 原文地址:https://www.cnblogs.com/markjiang7m2/p/ ...