原文地址:JavaScript基础心法——thisjavascript
欢迎star。html
若是有错误的地方欢迎指正。java
看看这个有着深不可测的魔力的this
究竟是个什么玩意儿 ~git
在传统面向对象的语言中,好比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
吧~
首先须要理解调用位置,调用位置就是函数在代码中被调用的位置,而不是声明的位置。
经过分析调用栈(到达当前执行位置所调用的全部函数)能够找到调用位置。
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
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
函数是用来输出name
、age
和job
,其中自己没有name
和age
属性,咱们将这个函数绑定到person
这个对象上,输出了本属于person
的属性,说明此时this
是指向对象person
的。
若是传入一个原始值(字符串、布尔或数字类型)来当作this
的绑定对象, 这个原始值会被转换成它的对象形式(new String()
),这一般被称为“装箱”。
call
和apply
从this
的绑定角度上来讲是同样的,惟一不一样的是它们的第二个参数。
this
将永久地被绑定到了bind
的第一个参数。
bind
和call
、apply
有些类似。
var person = { name: "axuebin", age: 25 }; function say(){ console.log(this.name+":"+this.age); } var f = say.bind(person); console.log(f());
全部的箭头函数都没有本身的this
,都指向外层。
关于箭头函数的争论一直都在,能够看看下面的几个连接:
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
被绑定到正在构造的新对象。
经过构造函数建立一个对象其实执行这样几个步骤:
因此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
this
指向触发事件的元素,也就是始事件处理程序所绑定到的DOM节点。
var ele = document.getElementById("id"); ele.addEventListener("click",function(e){ console.log(this); console.log(this === e.target); // true })
this
指向所在的DOM元素
<button onclick="console.log(this);">Click Me</button>
在许多状况下JQuery的this
都指向DOM元素节点。
$(".btn").on("click",function(){ console.log(this); });
若是要判断一个函数的this
绑定,就须要找到这个函数的直接调用位置。而后能够顺序按照下面四条规则来判断this
的绑定对象:
new
调用:绑定到新建立的对象call
或apply
、bind
调用:绑定到指定的对象注意:箭头函数不使用上面的绑定规则,根据外层做用域来决定this
,继承外层函数调用的this
绑定。