分享时长:45 分钟 + 15分钟提问
分享两个在JS中非常重要、但又经常遇到的两个点。
JS 关键字:指向当前环境的上下文
在 DOM 事件中,this
指向当前的 DOM 元素对象。
在 HTML 事件(仅为 addEventListener
添加时),this
指向了接收事件的 HTML 元素
<style>
#box {
height: 300px;
line-height: 300px;
text-align: center;
}
</style>
<body>
<div id="box">Hello World</div>
<script>
function bluify() {
console.log(this);
this.style.backgroundColor = "#00CCFF";
this.innerHTML =
this.innerHTML === "Hello World" ? "你好,世界" : "Hello World";
}
box.addEventListener("click", bluify, false);
</script>
</body>
Window
Global
function func() {
console.log(this); // Window or global
}
func();
this
指向当前的对象
const xiaoming = {
name: "小明",
getName() {
console.log(this.name);
},
};
xiaoming.getName(); // 小明
function Person(name, sex, age) {
this.name = name;
this.sex = sex;
this.age = age;
}
let xiaoming = new Person("小明", "男", 20);
console.log(xiaoming); // { name: '小明', sex: '男', age: 20 }
this
指向第一个参数
const xiaoming = {
name: "小明",
getName() {
console.log(this.name);
},
};
const xiaohong = {
name: "小红",
};
xiaoming.getName.call(xiaohong); // 小红
原因: 用于纠正 this
指向不达预期的问题
应用场景: 比如在 setTimeout
中的函数
用法:let that = this;
普通函数 VS 箭头函数
var name = "window";
let obj = {
name: "obj",
outout1() {
let that = this;
setTimeout(function() {
console.log("普通函数", that.name);
}, 1000);
},
outout2() {
setTimeout(() => {
console.log("箭头函数", this.name);
}, 1000);
},
};
obj.outout1(); // 普通函数 obj
obj.outout2(); // 普通函数 obj
因为箭头函数的this
是在定义的时候就确定的,使用它可以少写一步 this
指向,推荐使用。
eval()
传入函数
// setTimeout / setInterval 使用
setTimeout(
(...args) => {
let sum = args.reduce((p, c) => p + c);
console.log(args, sum); //[ 1, 2, 3 ] 6
},
1000,
1,
2,
3
);
// 这段代码的意思是:在 1 秒后将这个函数推入执行栈,然后传递参数1,2,3到函数中
一秒后开始计算 1,2,3 的和,然后输出。
传入字符串
setTimeout("alert(0)", 2000);
可以接受一个字符串,默认通过 eval()
解析后执行,但是 eval
函数非常耗性能,非特殊不推荐。
返回定时器的 ID ,用于清除定时器。
clearInterval(n);
clearTimeout(n);
核心逻辑:N 秒推入执行栈,而不是 N 秒后执行,
使用场景:延迟执行某个操作时
问题:
异步
// for & setTimout
for (var i = 1; i <= 10; i++) {
setTimeout(() => {
console.log(i); // ??
}, 1000);
}
因为异步的原因,setTimeout
被延迟到下一次事件循环中执行。
forEach
forEach 不能跳出循环
let arr = [1, 2, 3];
arr.forEach((e) => {
console.log(e);
1, 2, 3;
e += 1;
if (e === 2) {
// break !X
// return !X
}
});
console.log(arr); // [1, 2, 3];
在forEach
中使用break
、return
等都不会跳出循环。
上列操作可以转换为for
操作
for (let i = 0; i < arr.length; i++) {
if (arr[i] === 2) {
break;
}
arr[i] += 1;
}
console.log(arr); // [ 2, 2, 3 ]
使用场景
定时器不准确的原因
案例代码:
假设有一个 HTTP 轮询,每一秒查询一次数据。
let startTime = new Date().getTime();
let count = 0;
setInterval(() => {
let i = 0;
while (i++ < 10000000); // 假设这里是查询数据带来的网络延迟,用来增加每次函数执行的时间
count++;
console.log(
"与原设定的间隔时差了:",
new Date().getTime() - (startTime + count * 1000),
"毫秒"
);
}, 1000);
代码在执行多次后,定时器会变得不准确,产生误差。
定时器不及时清楚(小程序中)
clear
的话会一直保存在内存中,造成内存泄漏。定时器不准确
解决方法:使用settimeout
模拟setinterval
// 自定义一个定时器
let timer = null;
function interval(func, wait) {
let interv = function() {
func.call(null);
timer = setTimeout(interv, wait);
};
timer = setTimeout(interv, wait);
}
// 使用定时器
interval(() => {
let date = new Date();
console.log("log..", `${date.getMinutes()}: ${date.getSeconds()}`);
}, 1000);
// 清楚定时器
setTimeout(() => {
clearTimeout(timer);
}, 1000 * 6);
定时器太多清楚不掉,造成内存泄漏
解决方法:批量清楚定时器
// 清楚当前页面的所有定时器
for (let i = 1; i < 100000; i++) {
clearInterval(i);
clearTimeout(i);
}
建议及时保存定时器的id
,用于清除。
问题描述 在工作中想要实现如下效果: 解决思路 在 div 标签中添加一个 relative...
dreamweaver cs6怎么汉化?dreamweaver cs6网页设计软件CSS界面都是英文看不懂,...
话不多说,先来看一下效果图 源代码如下 !DOCTYPE htmlhtml lang=enhead meta ch...
在很多网站上我们都看到input输入框显示提示文字,让我们一起来看看如果在input...
编者按:本文是Teambition团队@娄昊川 的供稿文章,Teambition是一个简单易用的...
许久没有写博客了,最近有个H5启动APP原生页面的需求,中间遇上一些坑,看了些网...
经历了两天不懈努力,终于恢复了一次误操作删除的生产服务器数据。 对本次事故过...
一、从视频中获得图像 从视频中获得,主要是让视频跳到所需要的帧,然后暂停播放...
Meta声明标注步骤: 1.梳理所有与手机页存在一一对应关系的PC页,用于添加Meta声...
概述 在存在账号体系的信息系统中,对身份的鉴定是非常重要的事情。 随着移动互...