this在全局作用域下
在大多数情况下,this都是出现在函数中
在全局作用域下,this 的指向:
- 浏览器:window( globalObject)
- Node 环境:{ }
🤔有时候我们会发现JS执行this指向的结果会不一样,有什么规律吗?
this指向什么,跟函数所处的位置是没有关系的,而跟函数调用的方式有关系
function foo() {
console.log(this);
}
var obj = {
foo: foo
}
foo(); // 默认绑定
obj.foo(); // 隐式绑定
foo.call('a') // 显式绑定
this的默认绑定
当独立函数调用时,this 默认绑定(独立函数指函数没有被绑定到某个对象上进行调用)
function foo() {
console.log(this);
}
var obj = {
foo: foo
}
foo(); // 默认绑定
而默认绑定this在浏览器的指向是 window( globalObject)
this的隐式绑定
当通过某个对象发起的函数调用时,this 隐式绑定
function foo() {
console.log(this);
}
var obj = {
foo: foo
}
obj.foo(); // 隐式绑定
而隐式绑定this在浏览器的指向是 发起函数调用的对象(上面代码 this 的指向就是 obj 这个对象)
前提条件:必须在调用的对象内部有一个对函数的引用 (比如一个属性),不然会找不到函数而报错
var obj = {
foo: foo
}
🤔如果不想要在对象上添加属性,但又想绑定这个对象要怎么办呢?
那就要用到显示绑定了
this的显示绑定——call/apply/bind
调用call/apply方法就可以手动地指定函数中this的指向对象
function foo() {
console.log(this);
}
// foo.apply('a')
foo.call('a') // 显式绑定
🤔 call 和 apply 有什么区别呢?
如果只是单纯的指定对象,那他们的区别不大,它们主要的区别在于传递参数的形式
call 和 apply 的区别
这两个函数的第一个参数都要求是一个对象,后面的参数,call是参数列表,apply是数组
function sum(num1,num2) {
console.log('this指向的对象为' + this, num1 + num2)
}
sum.call('call', 10, 20)
sum.apply('apply', [10,20])
用bind来绑定
通过bind来绑定就不用一直调用call/apply方法来进行绑定(相当于用bind绑定一次可用多次)
function foo() {
console.log(this);
}
var newFoo = foo.call('a')
newFoo()
newFoo()
function foo() {
console.log(this);
}
var newFoo = foo.bind('a')
newFoo()
newFoo()
🤔这里就有一个问题了: newFoo( )是一个独立函数调用吧,那它为什么不是指向window而是指向 ‘a’
是因为如果默认绑定和显示绑定一起出现,则显式绑定起作用,显示绑定优先级更高
this的new绑定
除了上面的默认绑定、隐式绑定和显式绑定,我们还可以通过一个new关键字来绑定对象
当我们通过一个new关键字调用一个函数时(构造器),这个时候this是在调用这个构造器时的对象
function Pet(name,hobby){
this.name = name
this.hobby = hobby
}
var p1 = new Pet('三号楼', 'eat')
console.log(p1.name,p1.hobby) //三号楼 eat
规则绑定的优先级
默认绑定 < 隐式绑定 < 显示绑定 < new 关键字绑定
箭头函数
简单了解一下箭头函数
箭头函数的构成:
- ( ) : 参数
- => : 箭头
- { } : 函数的执行体
nums.forEach((item, index,arr) => {})
一些常见的简写:
- 如果参数只有一个,( ) 可以省略
num.forEach(item => {
console.log(item)
})
- 如果函数执行体只有一行代码,那么 { } 也可以省略
num.forEach(item => console.log(item))
- 如果只有一行代码且这行代码返回一个对象
var foo = () => ({ a: 1, b: 2})
注:箭头函数不会绑定this、arguments属性,不能与new一起使用,会报错
就是说上面四种this绑定方法对箭头函数都不适用,箭头函数的this取决于上层作用域
箭头函数中this的指向
var obj = {
data: [],
getData: function () {
setTimeout(() => {
var a = [1, 2, 3]
this.data = a // 此处的this指向obj
}, 2000)
}
}
obj.getData()
扩:settimeout和forEach中的this指向
setTimeout(function () {
console.log(this)
}, 1000)
// this 的指向是window
var foo = [1, 2, 3]
foo.forEach(function (item) {
console.log(item, this);
}, "a")
// forEach 中this的指向是第二个参数