环境对象
环境对象this: 谁调用我我就是谁
this指向取决于函数的调用:
- 普通函数 : 函数名() this->window
- 构造函数 : new 函数名() this->new创建的实例对象
- 对象方法: 对象名.方法() this->对象
<script>
function fun(params) {
console.log(this);
}
// 1.普通函数
fun() //window
// 2.构造函数
new fun() //new创建的对象
let obj = {
name: '万叶',
age: 18,
eat: fun
}
// 3.对象方法
obj.eat() //obj
</script>
总结: this指向三选一,先找new,后找点
修改this的指向的三种方法
默认情况下,函数内的this是固定的,无法被修改
如果想要修改函数内部this的指向,则需要使用上下文调用方法
上下文: 函数作用域 上下文只想:修改函数作用域内部this指向
1.call方法调用,同时指定被调用函数中this的值
<script>
// call方法调用,同时指定被调用函数中this的值
// 语法:
// fun.call(thisArg,arg1,arg2...)
// thisArg:在tun函数运行时指定的this值
// arg1,arg2:传递其他的参数
// 返回值就是函数的返回值,因为他就是调用函数
const obj = {
name: '万叶'
}
function fun(x, y) {
console.log(this); //window
console.log(x + y); //3
}
// 1.调用函数
// 2.改变this指向
fun.call(obj, 1, 2)
</script>
2.指向apply方法调用函数,同时指定被调用函数中this的值
<script>
// 语法:
// fun.apply(thisArg,[argsArray])
// thisArg:在fun函数运行时指定的this值
// argsArray:传递的值,必须包含在数组里面
// 返回值就是函数的返回值,因为就是在调用函数
// 因此apply主要跟数组有关系,比如使用Math.max()求数组的最大值
function fun(x, y) {
return x + y
}
// 调用函数,并传入参数
let fu = fun.apply(null, [1, 2])
console.log(fu); //3
</script>
apply的运用场景: 伪数组转真数组
<script>
// apply()使用场景:伪数组转真数组
// 1. 伪数组: 有数组三要素(下标,元素,长度),不能使用数组的方法
//伪书组本质是对象
let obj = {
0: 1,
1: 2,
2: 3,
length: 3
}
console.log(obj);
// 需求:有时候伪书组想要使用真数组的办法,就需要把为数组转换为真数组
// 1.把为数组元素取出来,push到真数组里面
let arr = []
arr.push(obj[0], obj[1], obj[2])
console.log(arr);
// 2.手动遍历循环添加
let arr = []
for (let i = 0; i < obj.length; i++) {
arr.push(obj[i])
}
console.log(arr);
//3.arr.push.apply(arr.为数组)
// 这里使用apply不是为了修改this,而是借助传参特点,自动遍历为数组/数组传参,多余第一个参数应该写arr(保持this不变)
let arr = []
arr.push.apply(arr, obj)
console.log(arr);
// ES6:为数组换真数组,固定静态方法Array.from(伪数组)
let newArr = Array.from(obj)
console.log(obj);
</script>
apply的运用场景: 求最大值
<script>
// apply(场景;求数组最大值)
let arr = [100, 200, 300, 400]
// 1.js基础:擂台思想
let max = arr[0]
for (let i = 0; i < arr.length; i++) {
max = max > arr[i] ? max : arr[i]
}
console.log(max);
// 2.js高级Math.amx()
let max1 = Math.max.apply(Math, arr)
console.log(max1);
//ES6: Math.max(...arr)
let max2 = Math.max(...arr)
console.log(max2);
</script>
3.bind()方法不会调用函数,但是能改变函数内部的this指向
<script>
// 语法:
// fun.bind(thisArg, arg1, arg2, ...)
// thisArg:在fun函数运行时指定的this值
// arg1, arg2:传递的其他参数
// 返回由指定this值和初始化参数改造的原函数拷贝(新函数)
// 因此当我们只想改变this指向,并且不想调用这个函数的时候,可以使用bind,比如改变定时器内部this指向
const obj = {
age: 18
}
function fun() {
console.log(this);
}
// 1.bind不会调用函数
// 2.改变this指向
// 3.返回值是个函数,但是这个函数里面的this时更改过的
const fu = fun.bind(obj)
fun() //window
//改变this指向的函数
fu() //obj
</script>
总结:
- 相同点:
- 都可以改变函数内部的this指向
- 区别点:
- call和apply会调用函数,并且改变函数内部this指向
- call和apply传递的参数不一样, call传递参数aru1, aru2...形式apply必须数组形式[arg]
- bind不会调用函数,可以改变函数内部this指向
- 主要应用场景:
- call调用函数并且可以传递参数
- apply经常跟数组有关系,比如借助于数学对象实现数组最大值最小值
- bind不调用函数,但是改变this指向比如改变定时器内部this的指向