类型转换
一:==
判断
console.log([ ]==false); console.log(![ ]==false)
分析
[]
是一个空数组,也就是一个Object
类型,既然是一个Object
,那么作判断条件时就会转换为true
- 当空数组和布尔值作比较时,会先将两者都转换为
Number
类型然后比较,比如false
就转换为0
,而[]
是空数组,也就转换为0
,然后两者比较结果为true
[]
本身是true
,然后加!
变成false
然后==
判断的时候 都变成number
类型去比较
console.log([]==false);//true
console.log(![] == false);//true
console.log(![]);//false
console.log([]==![]);//true
== 判断规则:
如果两个值类型相同,进行 === 比较。
如果两个值类型不同,他们可能相等。根据下面规则进行类型转换再比较:
1. 如果一个是null、一个是undefined,那么[相等]。
2. 如果一个是字符串,一个是数值,把字符串转换成数值再进行比较。
3. 如果任一值是 true,把它转换成 1 再比较;如果任一值是 false,把它转换成 0 再比较。
4. 如果一个是对象,另一个是数值或字符串,把对象转换成基础类型的值再比较。对象转换成基础类型,利用它的toString或者valueOf方法
二:关于函数
let arr = [1,2,3,10];
arr = arr.map(parseInt);
console.log(arr);
输出结果:[1, NaN, NaN, 3]
分析:
parseInt
一共有两个参数,第二个参数是进制数,可以通过alert(parseInt.length === 2)
来验证。
console.log(parseInt(10,3));
//将三进制数10转化为十进制数 结果为3map
方法在调用callback
函数时,会给它传递三个参数:当前正在遍历元素
、元素索引
、原数组本身
。- 第三个参数
parseInt
会忽视,但是第二个参数不会,也就是说,parseInt
把传过来的索引当成进制数来使用,从而返回了NaN。
如果想要返回目标值,可以这样修改:
function returnInt(e){
return parseInt(e,10);
}
["1","2","3"].map(returnInt);
for…in和for…of的区别
解析:
- for…in是ES5的标准,该方法遍历的是对象的属性名称(key:键名)。一个Array对象也是一个对象,数组中的每个元素的索引被视为属性名称,所以在使用for…in遍历Array时,拿到的是每个元素索引
- for … in对Array的循环得到的是String而不是Number。
- for…in…遍历对象会遍历出对象的所有可枚举的属性
- for…of是ES6的标准,该方法遍历的是对象的属性所对应的值(value:键值)。所以它用来遍历数组时得到每个元素的值
类数组对象不能使用for(var key in elements)进行遍历,这是因为类数组的最后一个哈希的键值对是length:n n代表数组长度
var a = ['A','B','C'];
var s = new Set(['A','B','C']);
var m = new Map([[1:'x'],[2:'y'],[3,'z']]);
//遍历数组
for(var x of a){
alert(x);//输出的是值 A B C
}
for(var x in a){
alert(x);//输出的是下标 0 1 2
}
//遍历Set集合
for(var x of s){
alert(x);//输出的是Set集合每个元素的值 A B C
}
for(var x in s){
alert(x);// 不起作用,不能使用for...in循环遍历Set集合
}
//遍历Map集合
for(var x of m){
alert(x[0]+"="+x[1]);//既可以拿到键名,也可以拿到键值,输出的是值 A B C
}
for(var x in m){
alert(x[0]+"="+x[1]);//for...in循环不能用于遍历Map
}
防抖和节流
防抖
防抖原理:事件响应函数在一段时间后才执行,如果在这段时间内再次调用,则重新计算执行时间。可理解为通过setTimeout的方式,在一定时间间隔内,将多次触发转变成一次触发。
应用场景:
- scroll时间滚动触发
- 搜索框输入查询
- 表单验证
- 按钮提交事件
- 浏览器窗口缩放
const button = document.querySelector('input');
function payMoney() {
console.log('支付');
}
function debounce(func, delay) {
let timer;
return function () {
//需要清除延时 就需要设置名字
let context = this;
let args = arguments;
clearTimeout(timer);
timer = setTimeout(function () {
func.apply(context, args);
}, delay)
}
//采用return返回函数 而不是直接写函数 防止函数直接执行
}
button.addEventListener('click', debounce(payMoney, 1000));
//在1s内点击多少次函数都只执行一次
//注意 this指向的变化和参数 timer的设置 高阶函数的使用return
节流
原理:如果你持续触发事件,每隔一段时间,只执行一次操作,可理解为减少一段时间之内事件的触发频率。
应用场景:
- DOM元素的拖拽实现功能
- 射击游戏
- 计算鼠标移动的距离
- 监听scroll滚动事件
function throttle(func, delay) {
let timer;
return function () {
let context = this;
let args = arguments;
if (timer) {
return;
}
timer = setTimeout(function () {
fun.apply(context, args);
timer = null;
}, delay)
}
}
window.addEventListener('resize', throttle(coloring, 2000));
另一种写法:利用Date
function throttle(func, delay) {
let pre = 0;
return function () {
let now = new Date();
if(now - pre > dalay){
func();
pre = now;
}
}
}
window.addEventListener('resize', throttle(coloring, 2000));