之前很久的时间,因为研究不深,对于this的值一直模模糊糊,不是很清楚,最近有空做了一些研究,终于彻底弄明白了this到底为何物。

首先, 先抛出一个定论:”在Javascript中,this关键字永远都指向函数(方法)的所有者”。

全局上下文

在全局上下文中(在任何函数体外部),this指代全局对象,无论是否在严格模式下。

(注:全局对象没有名称,视具体的js环境而定义,在浏览器环境下为window)

console.log(this.document === document);  //true

//在浏览器中,全局对象为window对象
console.log(this === window) //true this.a = 37;
console.log(window.a); // =>37

函数上下文

在函数内部,this的值取决于函数如何调用。

直接调用

function f1() {
return this;
} f1() === window; // => true function makeNoSense(x) {
this.x = x;
} makeNoSense(5);
x;// x 已经成为一个值为 5 的全局变量

在上面的例子中,this的值不是由函数调用设定。因为代码不是在严格模式下执行,this 的值总是一个对象且默认为全局对象。

function f2(){
"use strict"; // 这里是严格模式
return this;
} f2() === undefined; // true

在严格模式下,this 是在进入运行环境时设置的。若没有定义,this的值将维持undefined状态。同时它也能设置成任意值,比如 null 或者42 或者“I am not this”。

对象方法中的this

在以对象的方法的方式调用函数时,他们的this是调用该函数的对象。

下面的例子中,当o.f()被调用时,函数内的this将绑定到o对象。

var o = {
prop: 37,
f: function() {
return this.prop;
}
}; console.log(o.f()); // logs 37

注意,在何处或者如何定义调用函数完全不会影响到this的行为。在上一个例子中,我们在定义o的时候为其成员f定义了一个匿名函数。但是,我们也可以首先定义函数然后再将其附属到o.f。这样做this的行为也一致:

var o = {prop: 37};

function independent() {
return this.prop;
} o.f = independent; console.log(o.f()); // logs 37

这说明this的值只与函数 f 作为 o 的成员被调用有关系。

类似的,this 的绑定只受最靠近的成员引用的影响。在下面的这个例子中,我们把一个方法g当作对象o.b的函数调用。在这次执行期间,函数中的this将指向o.b。事实上,这与对象本身的成员没有多大关系,最靠近的引用才是最重要的。

o.b = {
g: independent,
prop: 42
};
console.log(o.b.g()); // logs 42

原型链中的 this

相同的概念在定义在原型链中的方法也是一致的。如果该方法存在于一个对象的原型链上,那么this指向的是调用这个方法的对象,表现得好像是这个方法就存在于这个对象上一样。

var o = {
f : function(){
return this.a + this.b;
}
};
var p = Object.create(o);
p.a = 1;
p.b = 4; console.log(p.f()); //

在这个例子中,对象p没有属于它自己的f属性,它的f属性继承自它的原型。但是这对于最终在o中找到f属性的查找过程来说没有关系;查找过程首先从p.f的引用开始,所以函数中的this指向p。也就是说,因为f是作为p的方法调用的,所以它的this指向了p。这是JavaScript的原型继承中的一个有趣的特性。

构造函数中的 this

当一个函数被作为一个构造函数来使用(使用new关键字),它的this与即将被创建的新对象绑定。

call 和 apply

当一个函数的函数体中使用了this关键字时,通过所有函数都从Function对象的原型中继承的call()方法和apply()方法调用时,它的值可以绑定到一个指定的对象上。

function add(c, d){
return this.a + this.b + c + d;
} var o = {a:1, b:3}; // The first parameter is the object to use as 'this', subsequent parameters are passed as
// arguments in the function call
add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 // The first parameter is the object to use as 'this', the second is an array whose
// members are used as the arguments in the function call
add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34

使用 call 和 apply 函数的时候要注意,如果传递的 this 值不是一个对象,JavaScript 将会尝试使用内部 ToObject 操作将其转换为对象。因此,如果传递的值是一个原始值比如 7 或 'foo' ,那么就会使用相关构造函数将它转换为对象,所以原始值 7 通过new Number(7)被转换为对象,而字符串'foo'使用 new String('foo') 转化为对象,例如:

function bar() {
console.log(Object.prototype.toString.call(this));
} bar.call(7); // [object Number]

bind 方法

ECMAScript 5 引入了 Function.prototype.bind。调用f.bind(someObject)会创建一个与f具有相同函数体和作用域的函数,但是在这个新函数中,this将永久地被绑定到了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

DOM事件处理函数中的 this

当函数被用作事件处理函数时,它的this指向触发事件的元素(一些浏览器在动态添加监听器时不遵守这个约定,除非使用addEventListener 这句不太确定翻译的是否正确)。

// 被调用时,将关联的元素变成蓝色
function bluify(e){
console.log(this === e.currentTarget); // 总是 true // 当 currentTarget 和 target 是同一个对象是为 true
console.log(this === e.target);
this.style.backgroundColor = '#A5D9F3';
} // 获取文档中的所有元素的列表
var elements = document.getElementsByTagName('*'); // 将bluify作为元素的点击监听函数,当元素被点击时,就会变成蓝色
for(var i=0 ; i<elements.length ; i++){
elements[i].addEventListener('click', bluify, false);
}

对象方法中内建函数中this

对象方法中内建函数中this绑定到全局对象上。这属于 JavaScript 的设计缺陷,正确的设计方式是内部函数的 this 应该绑定到其外层函数对应的对象上,为了规避这一设计缺陷,聪明的 JavaScript 程序员想出了变量替代的方法,约定俗成,该变量一般被命名为 that(self)。

var point = {
x : 0,
y : 0,
moveTo : function(x, y) {
var that = this;
// 内部函数
var moveX = function(x) {
that.x = x;
};
// 内部函数
var moveY = function(y) {
that.y = y;
}
moveX(x);
moveY(y);
}
};
point.moveTo(1, 1);
point.x; //==>1
point.y; //==>1

JS中this的值到底为何?的更多相关文章

  1. 图文结合深入理解 JS 中的 this 值

    图文结合深入理解 JS 中的 this 值 在 JS 中最常见的莫过于函数了,在函数(方法)中 this 的出现频率特别高,那么 this 到底是什么呢,今天就和大家一起学习总结一下 JS 中的 th ...

  2. js中以键值对的形式当枚举

    js中以键值对的形式当枚举var Penum= { B: "姓名", C: "所属居委", D: "证件号", E: "性别&qu ...

  3. 图文结合深入理解JS中的this值

    文章目录 Js 中奇妙的this值 1. 初探this 2. this指向总结 2.1 普通函数调用 2.2 对象的方法调用 2.3 构造函数调用 2.4 利用call,apply,bind方法调用函 ...

  4. 页面上有两个元素id相同,js中如何取值

    页面上有两个table,id都是”cont2",现要在js中取到这两个table,改变样式. js实现: var tab2=document.all.cont2(1);var  tab=do ...

  5. asp.net通过后台代码给前台设置css样式,下拉列表在js中的取值

    后台根据不同的用户登陆隐藏或显示前台div标签 前台: 将div声明成服务器端控件 <div id="div1" runat="server">.. ...

  6. Js 中的原始值和引用值

    最近遇写 node.js 时到一个问题,把对象当赋值给数组成员时总是出错,比如下面的代码, var Arr = new Array(); var Obj = new Object(); for(var ...

  7. input框中的value值到底是什么

    value 属性为 input 元素设定值. 对于不同的输入类型,value 属性的用法也不同: type="button", "reset", "s ...

  8. js中的bool值转换及"&&" 、"||"、 "!!"详解

    bool值转换 数据类型 bool值转化 undefined undefined 转化为 false Object null 转化为false,其他为 true Boolean false 转化为 f ...

  9. 关于js中的取值问题

    像这样是获取不到值的,弹出的消息是 underfined:<html><style type="text/css">input { border: 1px ...

随机推荐

  1. EXE加锁器 只是思路

    代码有点乱 但是我不想整理 // AddBoxDlg.cpp : 实现文件 // #include "stdafx.h" #include "AddBox.h" ...

  2. 用markdown学习写出总结

    # PS### 快捷键:CTRL+N(新建)CTRL+1. **切片**- 套索,磁性套索,椭圆,矩形选框.2. **印章** 仿制图章工具,图案图章工具3. 钢笔4. 油漆桶5. 吸管工具, *** ...

  3. Bootstrap <基础二十二>超大屏幕(Jumbotron)

    Bootstrap 支持的另一个特性,超大屏幕(Jumbotron).顾名思义该组件可以增加标题的大小,并为登陆页面内容添加更多的外边距(margin).使用超大屏幕(Jumbotron)的步骤如下: ...

  4. Visor 应用之一 通过ER 设计生成数据库脚本和实体对象

    前言 Visor(http://www.visor.com.cn)   是一个基于HTML5 Canvas 开发的IDE 框架和设计开发平台,有关Visor的设计架构和技术应用,在以后的文章里会逐渐跟 ...

  5. MEAN.JS入门

    MEAN stands for: 下载:MongoDB下载文件 百度盘共享 运行命令:mongod 提示你dbpath(/data/db/) does not exist, terminating 创 ...

  6. js2

    1.JS的三种输出方式: alert("");console.log("");document.write(""); 2.流程控制语句: a ...

  7. Linux学习 :SPI通讯协议

    SPI接口的全称是"Serial Peripheral Interface",意为串行外围接口,是Motorola首先在其MC68HCXX系列处理器上定义的.SPI接口主要应用在E ...

  8. EF升级6.0数据库链接不上问题

    昨天搞了个mvc4  先从net4.0 升级4.5后 数据库连接不上了,  然后升级ef未最新的6.1  居然还报错 不到方法:“System.Data.Objects.ObjectContext S ...

  9. linux下系统编程C环境搭建

    一.系统安装 我使用的是VMware8下的ubuntu12.04,这是培训老师说的,12.04相对来说,比较新,而且是5年长期支持版,不容易过时.对于系统的安装,我不想说很多,只是希望大家主义这几点: ...

  10. 玩转mysql-5.7.9-winx64.zip解压版

    解压zip文件,放到D盘 追加\bin到Path环境变量 修改my-default.ini,# basedir =D:\mysql_5.7.9_winx64# datadir =D:\mysql_5. ...