JS高阶 this指向 day-03
this的指向是当我们调用函数的时候决定的,调用的方法不同我们的this指向也不同
1、在普通函数中的this指向window对象(但是在严格模式下却是undefined)
2、在构造函数中的this指向了实例化的对象
3、在对象的属性和方法中的this指向了当前对象
4、在事件绑定函数中的this指向了事件的绑定者
5、在定时器函数中的this指向了window对象
6、在立刻执行函数中的this指向了window对象
7、在构造函数的prototype中的this指向了实例化对象
那这些this指向就不能改变吗答案是肯定的,能,通过以下方法可以更改this指向
1、Function.prototype.call()-----------call()方法
call();使用一个指定的this值调用一个函数(简单理解为调用函数的方式,但是它是可以改变函数的this指向的)
var obj={
name:"小明";
};
function fun(a,b){
console.log(this);
cosnole.log(a+b);
};
fun(1,2);//此时的this指向是window,运行结果是3
fun.call(obj,4,5);//此时的this指向是obj,运行结果是9
2、Function.prototype.apply()-------apply()方法
apply();方法调用一个函数。简单理解为调用函数的方式,但是它可以改变函数的this指向。应用场景和数组有关
var obj={
name:"小花";
}
function fun(a,b){
console.log(this);
console.log(a+b);
};
fun(1,2);//此时结果是3,this指向window
fun.apply(obj,[3,4]);//此时的this结果是对象obj,参数使用的是数组,结果为3
3、Function.prototype.bind()---------bind()方法
bind(); 方法不会调用函数,但是能改变函数内部的this,返回的是原函数改变的this之后的新函数。bind()的特点是不会立刻调用,如果想要改变this指向还不想调用函数可以选择这个
var obj2={
name:"小明";
}
function fun(a,b){
console.log(this);
console.log(a+b);
}
var rel=fun.bind(obj2,1,2);//此时的rel是bind返回的新函数
rel();//调用新函数
call()、apply()、bind() 三者的异同(重点)
相同点:
都可以改变this指向,传入参数的时候都使用逗号隔开
不同点:
1、call()和apply()可以改变函数内部this指向,会立刻调用函数,但是bind不会立刻调函数
2、call()和apply()传递的参数不一样,call传递的参数使用逗号隔开就可以了,而apply()除使用逗号隔开外还需要传递数组作为参数
3、bind()改变this指向后需要手动调用
应用场景:(重点)
1、call()的应用场景:用于判断数据类型(最精准的数据类型判定方法)
Object.prototype.toString.call(new RegExp);
2、apply()的应用场景:用于Math.max或Math.min方法找数组中的最大值或最小值
var arr=[1,23,345,56,7,80,55];
var rel=Math.max.apply(Math,arr);
3、bind()的应用场景:用于改变定时器,给定时器传递参数
<body>
<button>5秒之后再次点击</button>
<button>5秒之后再次点击</button>
<button>5秒之后再次点击</button>
<button>5秒之后再次点击</button>
<button>5秒之后再次点击</button>
<script>
var btn = document.querySelectorAll("button");
// var timerId = null;
for (var i = 0; i < btn.length; i++) {
btn[i].onclick = function () {
this.disabled = true;
var num = 5;
var timerId = setInterval(function () {
num--;
if (num <= 0) {
this.disabled = false;
this.innerText = "5秒之后再次点击";
clearInterval(timerId);
} else {
this.innerText = num + "秒之后再次点击";
}
}.bind(this), 1000);
}
}
// .bind(xx,xx)
</script>
</body>
</html>
定时器传参
var num=500;
setTimeout("fun(num)",500);//给定时器中的函数加上引号,作为脚本存在
funciton fun(num){
console.log("500毫秒之后打印");
}
数据类型的检测方式(共四种)
1、typeof 用于检测简单数据类型
2、instanceof 用于检测发杂数据类型
3、constructor 用于检测当前对象的构造函数
4、Object.prototype.toString.call()
最精确的数据类型检测方式
内置对象Array的操作方法
1、数组方法forEach遍历数组
arr.forEach(function(value,index,array){
//参数value是当前数组元素
//参数index是元素的索引下标
//参数array是当前数组
})
//相当于数组遍历的for循环没有返回值
2、数组的方法map遍历数组
map()方法返回一个新数组,数组中的元素为元素数据经过函数处理过后的新数组
map()方法按照原始数组顺序依次处理元素
map()不会对空数组进行检测 map()不改变原数组,返回值是经过处理后的新数组
var arr=[1,2,34,5,6,7];
var rel=arr.map(function(value){
return value*4;
})
cosnole.log(rel);
3、数组方法filter过滤数组
filter()方法创建一个新的数组,数组中的元素是通过检测检测只当数组中符合条件的所有元素
var arr=[1,2,4,547,96,77,45,23];
var rel=arr.filter(function(value){
return value>50;
});
console.log(rel);
4、数组方法some
some查找数组中是否有满足5条件的元素,如果数组中有元素满足条件就返回true,否则返回false
var arr=[1,35,6,89,0,76];
var rel=arr.some(function(value){
return value<1;
});
console.log(rel);//本身和循环一样,但是只要有元素满足条件就会立刻中止循环
5、数组方法every
every()方法用于检测数组中所有元素是否都符合指定条件
every方法使用指定函数检测数组中的所有元素:
array.every(function(value,index,arr))
如果有一个不满足条件则整个表达式返回false,且剩余的元素不会再进入检测
如果所有元素都满足条件才返回true
**注意:**every()不会对空数组进行检测
every()不会改变原数组
6、数组方法find
find()方法返回通过测试的数组的第一个元素的值
find()方法为每个元素都调用依次调用判断直到直到找到符合条件的元素
如果没有符合条件的元素返回undefined
var arr=[1,3,546,8,9,45,645]
arr.find(function(value){
return value>30;
})
7、数组方法reduce
reduce()方法接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值
arr.reduce(function(total,value,index,arr){},initialValue)
total:必需,初始值
value:必须,当前元素
index:可选,元素索引
arr: 可选,当前元素所属的数组对象
initialValue:作为第一次调用的初始值,也就是total的值,可传可不传,也可以传递空数组([])
返回值:最终计算的一个值