分享時長:45 分鐘 + 15分鐘提問html
分享兩個在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
指向第一個參數app
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
,用於清除。