JavaScript基础心法——this

原文地址:JavaScript基础心法——thisjavascript

欢迎star。html

若是有错误的地方欢迎指正。java


看看这个有着深不可测的魔力的this究竟是个什么玩意儿 ~git

什么是this

在传统面向对象的语言中,好比Java,this关键字用来表示当前对象自己,或当前对象的一个实例,经过this关键字能够得到当前对象的属性和调用方法。es6

在JavaScript中,this彷佛表现地略有不一样,这也是让人“讨厌”的地方~github

ECMAScript规范中这样写:浏览器

this 关键字执行为当前执行环境的 ThisBinding。app

MDN上这样写:函数

In most cases, the value of this is determined by how a function is called.
在绝大多数状况下,函数的调用方式决定了this的值。this

能够这样理解,在JavaScript中,this的指向是调用时决定的,而不是建立时决定的,这就会致使this的指向会让人迷惑,简单来讲,this具备运行期绑定的特性。

参考资料:this - JavaScript | MDN

来看看不一样的状况五花八门的this吧~

调用位置

首先须要理解调用位置,调用位置就是函数在代码中被调用的位置,而不是声明的位置。

经过分析调用栈(到达当前执行位置所调用的全部函数)能够找到调用位置。

function baz(){
  console.log("baz");
  bar();
}
function bar(){
  console.log("bar");
  foo();
}
function foo(){
  console.log("foo");
}
baz();

当咱们调用baz()时,它会以此调用baz()bar()foo()

对于foo():调用位置是在bar()中。
对于bar():调用位置是在baz()中。
而对于baz():调用位置是全局做用域中。

能够看出,调用位置应该是当前正在执行的函数的前一个调用中。

全局上下文

在全局执行上下文中this都指代全局对象。

  • this等价于window对象
  • var === this. === winodw.
console.log(window === this); // true
var a = 1;
this.b = 2;
window.c = 3;
console.log(a + b + c); // 6

在浏览器里面this等价于window对象,若是你声明一些全局变量,这些变量都会做为this的属性。

函数上下文

在函数内部,this的值取决于函数被调用的方式。

直接调用

this指向全局变量。

function foo(){
  return this;
}
console.log(foo() === window); // true

call()、apply()

this指向绑定的对象上。

var person = {
  name: "axuebin",
  age: 25
};
function say(job){
  console.log(this.name+":"+this.age+" "+job);
}
say.call(person,"FE"); // axuebin:25
say.apply(person,["FE"]); // axuebin:25

能够看到,定义了一个say函数是用来输出nameagejob,其中自己没有nameage属性,咱们将这个函数绑定到person这个对象上,输出了本属于person的属性,说明此时this是指向对象person的。

若是传入一个原始值(字符串、布尔或数字类型)来当作this的绑定对象, 这个原始值会被转换成它的对象形式(new String()),这一般被称为“装箱”。

callapplythis的绑定角度上来讲是同样的,惟一不一样的是它们的第二个参数。

bind()

this将永久地被绑定到了bind的第一个参数。

bindcallapply有些类似。

var person = {
  name: "axuebin",
  age: 25
};
function say(){
  console.log(this.name+":"+this.age);
}
var f = say.bind(person);
console.log(f());

箭头函数

全部的箭头函数都没有本身的this,都指向外层。

关于箭头函数的争论一直都在,能够看看下面的几个连接:

ES6 箭头函数中的 this?你可能想多了(翻译)

关于箭头函数this的理解几乎彻底是错误的 #150

MDN中对于箭头函数这一部分是这样描述的:

An arrow function does not create its own this, the this value of the enclosing execution context is used.
箭头函数会捕获其所在上下文的this值,做为本身的this值。

function Person(name){
  this.name = name;
  this.say = () => {
    var name = "xb";
    return this.name;
  }
}
var person = new Person("axuebin");
console.log(person.say()); // axuebin

箭头函数经常使用语回调函数中,例如定时器中:

function foo() {  
  setTimeout(()=>{
    console.log(this.a);
  },100)
}
var obj = {
  a: 2
}
foo.call(obj);

附上MDN关于箭头函数this的解释:

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Functions/Arrow_functions#不绑定_this

做为对象的一个方法

this指向调用函数的对象。

var person = {
  name: "axuebin",
  getName: function(){
    return this.name;
  }
}
console.log(person.getName()); // axuebin

这里有一个须要注意的地方。。。

var name = "xb";
var person = {
  name: "axuebin",
  getName: function(){
    return this.name;
  }
}
var getName = person.getName;
console.log(getName()); // xb

发现this又指向全局变量了,这是为何呢?

仍是那句话,this的指向得看函数调用时。

做为一个构造函数

this被绑定到正在构造的新对象。

经过构造函数建立一个对象其实执行这样几个步骤:

  1. 建立新对象
  2. 将this指向这个对象
  3. 给对象赋值(属性、方法)
  4. 返回this

因此this就是指向建立的这个对象上。

function Person(name){
  this.name = name;
  this.age = 25;
  this.say = function(){
    console.log(this.name + ":" + this.age);
  }
}
var person = new Person("axuebin");
console.log(person.name); // axuebin
person.say(); // axuebin:25

做为一个DOM事件处理函数

this指向触发事件的元素,也就是始事件处理程序所绑定到的DOM节点。

var ele = document.getElementById("id");
ele.addEventListener("click",function(e){
  console.log(this);
  console.log(this === e.target); // true
})

HTML标签内联事件处理函数

this指向所在的DOM元素

<button onclick="console.log(this);">Click Me</button>

jQuery的this

在许多状况下JQuery的this都指向DOM元素节点。

$(".btn").on("click",function(){
  console.log(this); 
});

总结

若是要判断一个函数的this绑定,就须要找到这个函数的直接调用位置。而后能够顺序按照下面四条规则来判断this的绑定对象:

  1. new调用:绑定到新建立的对象
  2. callapplybind调用:绑定到指定的对象
  3. 由上下文对象调用:绑定到上下文对象
  4. 默认:全局对象

注意:箭头函数不使用上面的绑定规则,根据外层做用域来决定this,继承外层函数调用的this绑定。

相关文章
相关标签/搜索