面向後端的前端技術分享

面向後端的前端技術分享

分享時長:45 分鐘 + 15分鐘提問html

分享兩個在JS中很是重要、但又常常遇到的兩個點。前端

思惟導圖

目的

  • 分享平常開發工做中常遇到的問題
  • 提高工做效率,編寫易維護的代碼
  • 瞭解前端技術的趨勢

This

JS 關鍵字:指向當前環境的上下文小程序

1. 事件中的 this

在 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>

2. 全局函數、匿名函數,this 指向是全局對象

  • 瀏覽器中指向 Window
  • Node 環境指向 Global
function func() {
  console.log(this); // Window or global
}
func();

3. 對象的方法調用

this 指向當前的對象網絡

const xiaoming = {
  name: "小明",
  getName() {
    console.log(this.name);
  },
};
xiaoming.getName(); // 小明

4. 構造函數內調用,this 指向實例對象

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 }

5. call/apply/bind 調用

this 指向第一個參數app

const xiaoming = {
  name: "小明",
  getName() {
    console.log(this.name);
  },
};
const xiaohong = {
  name: "小紅",
};
xiaoming.getName.call(xiaohong); // 小紅

this 複製引用

緣由: 用於糾正 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 指向,推薦使用。

定時器

  • setTimeout:規定 N 秒後執行
  • setInterval:規定 N 秒後循環執行

參數

  • 函數/字符串、字符串會觸發eval()
  • 時長毫秒(ms)
  • 傳入函數的參數列表

傳入函數

// 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);

setTimeout

核心邏輯:N 秒推入執行棧,而不是 N 秒後執行,

使用場景:延遲執行某個操做時

問題:

  • 設置 0 秒也會在下一個宏任務中執行(異步)
  • 定時器在 for 中輸出 1-10 的坑(forEach 不可跳出循環)

異步

// 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中使用breakreturn等都不會跳出循環。

上列操做能夠轉換爲for操做

for (let i = 0; i < arr.length; i++) {
  if (arr[i] === 2) {
    break;
  }
  arr[i] += 1;
}
console.log(arr); // [ 2, 2, 3 ]

setInterval

使用場景

  • 視頻學習的定時保存學時
  • 掃碼登陸的輪詢

問題

定時器不許確的緣由

  • N 秒後推入執行棧,而不是 N 秒後執行
  • 會由於前面有代碼在執行而致使時間變短

案例代碼:

假設有一個 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,用於清除。

相關文章
相關標籤/搜索