JS 里的 thishtml
- 在 function 内部被建立
- 指向调用时所在函数所绑定的对象(拗口)
- this 不能被赋值,但能够被 call/apply 改变
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
对象内部方法的this指向调用这些方法的对象:node
//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
普通函数内部的this分两种状况,严格模式和非严格模式。es6
//非严格模式下,this 默认指向全局对象window function f1(){ return this; } f1() === window; // true //而严格模式下, this为undefined function f2(){ "use strict"; // 这里是严格模式 return this; } f2() === undefined; // true
前面提到 this 是 “指向调用时所在函数所绑定的对象”, 这句话拗口但绝对正确,没有一个多余的字。
全局环境中有不一样的宿主对象,浏览器环境中是 window, node 环境中是 global。这里重点说下浏览器环境中的 this。
浏览器环境中非函数内 this 指向 window浏览器
alert(window=== this) // true
所以你会看很不少开源 JS lib 这么写缓存
(function() { // ... })(this);
或这样写app
(function() { // ... }).call(this);
好比 underscore 和 requirejs,大意是把全局变量 window 传入匿名函数内缓存起来,避免直接访问。至于为啥要缓存,这跟 JS 做用域链有关系,读取越外层的标识符性能会越差。dom
浏览器中比较坑人,非函数内直接使用 var 声明的变量默认为全局变量,且默认挂在 window 上做为属性。函数
var andy = '刘德华' alert(andy === window.andy) // true alert(andy === this.andy) // true alert(window.andy === this.andy) // true
由于这个特性,有些笔试题如requirejs
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。性能
当函数被当作监听事件处理函数时, 其 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);
内联事件中的this指向分两种状况:
对于延时函数内部的回调函数的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{...}
当函数经过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"}
若是采用 OOP 方式写 JS 代码,无可避免的会用到 this,方法内会访问类的内部属性(字段),也可能会调用类的另外一个方法。当类的方法内又有一个 function 时,好比浏览器端开发常常碰见的给 DOM 元素添加事件,这时若是事件处理器(handler)中的想调用类的一个方法,此时 handler 内的 this 是 dom 元素而非类的当前对象。这个时候,须要把 this 暂存,开发者发挥着本身的聪明才智留下了几种经典的命名** me, self, that, _this**。如
如:
通常会在每一个方法的第一句就把 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
箭头函数的一个重要特征就是颠覆了上面的一句话,再贴一次
判断 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对象,而普通函数则指向调用它的对象
原文参考:
http://www.javashuo.com/article/p-aloxbrqk-mm.html
http://www.cnblogs.com/dongcanliang/p/7054176.html