this指向
this指向什么
在浏览器中this的指向就是window
console.log(this) // window
但是不同的调用方式会有不一样的结果
function fun() {
console.log(this)
}
// 方式一:直接调用
fun() // window
const obj = {
name: 'qq',
foo: fun
}
// 方法二:把函数放在一个对象内进行调用
obj.foo() // obj对象
// 方法三:使用call/apply进行调用
fun.call('aa') // String{'aa'}对象
- this值的绑定跟其定义的位置没有关系
- this值的绑定跟其调用的位置以及调用的方式有关系
- this的值是在运行的时候进行绑定的
this的值是如何绑定的
默认绑定
当函数没有被绑定在一个对象上的时候进行调用时会进行默认绑定
function fun () {
console.log(this)
}
fun() // window
function test1() {
console.log(this); // window
test2();
}
function test2() {
console.log(this); // window
test3()
}
function test3() {
console.log(this); // window
}
test1();
function foo(func) {
func()
}
function bar() {
console.log(this); // window
}
foo(bar);
function fun(foo){
foo()
}
const obj = {
name:'qq',
foo: function(){
console.log(this)
}
}
fun(obj.foo) // window
隐式绑定
这是一种比较常见的绑定方式,就是函数的调用方式是通过一个对象发起的
必须在对象中的有一个属性进行引用了某个函数,正是这个引用使this的值绑定在了这个对象上
function fun() {
console.log(this)
}
const obj = {
name: 'qq',
fun: fun
}
obj.fun() // obj对象
function fun() {
console.log(this)
}
const obj1 = {
name:'qq1',
fun: fun
}
const obj2 = {
name: 'qq2',
obj: obj1
}
obj2.obj1.fun() // obj1对象
隐式丢失
function fun () {
console.log(this)
}
const obj = {
name: 'qq',
fun: fun
}
const a = obj.fun
a() // window
此时会发生隐式丢失的问题,因为a
在调用的时候没有绑定任何对象,也就没有形成隐式绑定,所以这个时候this的值是window
显式绑定
call、apply
通过call或apply绑定this对象
function fun(){
console.log(this)
}
fun.call(window) // window
fun.call({name: "qq"}) // {name:"qq"}
fun.call(111) // Number对象,存放111
bind函数
方案一:我们可以自己手写一个辅助函数进行绑定this的值
function fun() {
console.log(this)
}
function bind(func, obj) {
return function() {
return func.apply(obj,arguments)
}
}
var obj = {
name: 'qq'
}
var example = bind(fun, obj)
example() // bind对象
方案二: 使用 Function.prototype.bind
function fun () {
console.log(this)
}
var obj = {
name: 'qq'
}
var example = fun.bind(obj)
example() // obj对象
new绑定
javaScript中的函数可以当做一个类的构造函数来使用的,也就是可以使用new关键字
使用new关键字会执行以下操作:
- 创建一个全新的对象
- 这个对象会被执行Prototype连接
- 这个全新的对象会绑定到函数调用的this上(this的绑定)
- 如果函数没有返回其他对象,表达式会返回这个新对象
// 创建Person
function Person(name) {
console.log(this); // Person {}
this.name = name; // Person {name: "why"}
}
var p = new Person("why");
console.log(p);
优先级
new绑定 > 显示绑定(bind)> 隐式绑定 > 默认绑定
箭头函数
ES6语法新增了一个箭头函数语法
箭头函数不进行this的绑定,而是根据外层作用域来决定this的值
// 不使用箭头函数
var obj = {
data: [],
getData: function() {
var _this = this;
setTimeout(function() {
// 模拟获取到的数据
var res = ["abc", "cba", "nba"];
_this.data.push(...res);
}, 1000);
}
}
obj.getData();
下面可以在setTimeout中直接使用this了,因为箭头函数并不进行this的绑定,那么this的引用就会从上层作用域中找到对应的this
// 使用箭头函数
var obj = {
data: [],
getData: function() {
setTimeout(() => {
// 模拟获取到的数据
var res = ["abc", "cba", "nba"];
this.data.push(...res);
}, 1000);
}
}
obj.getData();