JavaScript速查表

来源:https://www.cnblogs.com/zhaoqingqing/p/18403172
-Advertisement-
Play Games

JavaScript速查表 本手冊絕大部分內容是從Airbnb JavaScript Style Guide精簡整理,將開發者們都明確的操作去掉,目的為了就是更快的速查。 此處為源地址。 譯制:HaleNing 目錄 基礎知識 類型 引用 對象 數組 解構 字元串 變數 屬性 測試 公共約束 註釋 ...


JavaScript速查表

  • 本手冊絕大部分內容是從Airbnb JavaScript Style Guide精簡整理,將開發者們都明確的操作去掉,目的為了就是更快的速查。
    此處為源地址

  • 譯制:HaleNing

目錄

基礎知識

類型

  • 基本類型
    最新的 ECMAScript 標准定義了 8 種數據類型,分別是
    • string
    • number
    • bigint
    • boolean
    • null
    • undefined
    • symbol (ECMAScript 2016新增)

所有基本類型的值都是不可改變的。但需要註意的是,基本類型本身和一個賦值為基本類型的變數的區別。變數會被賦予一個新值,而原值不能像數組、對象以及函數那樣被改變。

  • 引用類型
    • Object(包含普通對象-Object,數組對象-Array,正則對象-RegExp,日期對象-Date,數學函數-Math,函數對象-Function)
使用 typeof 運算符檢查:

undefined:typeof instance === "undefined"
Boolean:typeof instance === "boolean"
Number:typeof instance === "number"
String:typeof instance === "string
BigInt:typeof instance === "bigint"
Symbol :typeof instance === "symbol"
null:typeof instance === "object"。
Object:typeof instance === "object"

引用

推薦常量賦值都使用const, 值可能會發生改變的變數賦值都使用 let

為什麼?let const 都是塊級作用域,而 var是函數級作用域


// bad
var count = 1;
if (true) {
  count += 1;
}

// good, use the let and const 
let count = 1;
const pi =3.14;
if (true) {
  count += 1;
}

對象

  • 使用字面語法創建對象:

    // bad
    const item = new Object();
    
    // good
    const item = {};
    
  • 在創建具有動態屬性名稱的對象時使用屬性名稱:

    
    function getKey(k) {
      return `a key named ${k}`;
    }
    
    // bad
    const obj = {
      id: 5,
      name: 'San Francisco',
    };
    obj[getKey('enabled')] = true;
    
    // good
    const obj = {
      id: 5,
      name: 'San Francisco',
      [getKey('enabled')]: true,
    };
    
  • 屬性值簡寫,並且推薦將縮寫 寫在前面 :

    const lukeSkywalker = 'Luke Skywalker';
    //常量名就是你想設置的屬性名
    // bad
    const obj = {
      lukeSkywalker: lukeSkywalker,
    };
    
    // good
    const obj = {
      lukeSkywalker,
    };
    
    const anakinSkywalker = 'Anakin Skywalker';
    const lukeSkywalker = 'Luke Skywalker';
    
    // good
    const obj = {
      lukeSkywalker,
      anakinSkywalker,
      episodeOne: 1,
      twoJediWalkIntoACantina: 2,
      episodeThree: 3,
      mayTheFourth: 4,
    };
    
  • 不要直接調用 Object.prototype上的方法,如 hasOwnPropertypropertyIsEnumerableisPrototypeOf

    為什麼?在一些有問題的對象上,這些方法可能會被屏蔽掉,如:{ hasOwnProperty: false } 或空對象 Object.create(null)

    // bad
    console.log(object.hasOwnProperty(key));
    
    // good
    console.log(Object.prototype.hasOwnProperty.call(object, key));
    
    // best
    const has = Object.prototype.hasOwnProperty; 
    console.log(has.call(object, key));
    /* or */
    import has from 'has'; // https://www.npmjs.com/package/has
    console.log(has(object, key));
    
  • 對象拷貝時,推薦使用...運算符來代替Object.assign, 獲取大對象的多個屬性時,也推薦使用...運算符

    // very bad, 因為line2的操作更改了original
    const original = { a: 1, b: 2 };
    const copy = Object.assign(original, { c: 3 }); 
    // 將不需要的屬性刪除了
    delete copy.a; 
    
    // bad
    const original = { a: 1, b: 2 };
    const copy = Object.assign({}, original, { c: 3 }); // copy => { a: 1, b: 2, c: 3 }
    
    // good 使用 es6 擴展運算符 ...
    const original = { a: 1, b: 2 };
    // 淺拷貝
    const copy = { ...original, c: 3 }; // copy => { a: 1, b: 2, c: 3 }
    
    // rest 解構運算符
    const { a, ...noA } = copy; // noA => { b: 2, c: 3 }
    

數組

  • 用擴展運算符做數組淺拷貝,類似上面的對象淺拷貝:

    // bad
    const len = items.length;
    const itemsCopy = [];
    let i;
    
    for (i = 0; i < len; i += 1) {
      itemsCopy[i] = items[i];
    }
    
    // good
    const itemsCopy = [...items];
    
  • ... 運算符而不是 Array.from 來將一個可迭代的對象轉換成數組:

    const foo = document.querySelectorAll('.foo');
    
    // good
    const nodes = Array.from(foo);
    
    // best
    const nodes = [...foo];
    
  • 使用 Array.from 而不是 ... 運算符去做 map 遍歷。 因為這樣可以避免創建一個臨時數組:

    // bad
    const baz = [...foo].map(bar);
    
    // good
    const baz = Array.from(foo, bar);
    
  • 如果一個數組有很多行,在數組的 [ 後和 ] 前斷行 :

    
    // good
    const arr = [[0, 1], [2, 3], [4, 5]];
    
    const objectInArray = [
      {
        id: 1,
      },
      {
        id: 2,
      },
    ];
    
    const numberInArray = [
      1,
      2,
    ];
    

解構

  • 用對象的解構賦值來獲取和使用對象某個或多個屬性值:

    // bad
    function getFullName(user) {
      const firstName = user.firstName;
      const lastName = user.lastName;
    
      return `${firstName} ${lastName}`;
    }
    
    // good
    function getFullName(user) {
      const { firstName, lastName } = user;
      return `${firstName} ${lastName}`;
    }
    
    // best
    function getFullName({ firstName, lastName }) {
      return `${firstName} ${lastName}`;
    }
    
  • 數組解構:

    const arr = [1, 2, 3, 4];
    
    // bad
    const first = arr[0];
    const second = arr[1];
    const four = arr[3];
    
    // good
    const [first, second, _,four] = arr;
    
  • 多個返回值用對象的解構,而不是數組解構:

    // bad
    function processInput(input) {
      return [left, right, top, bottom];
    }
    
    // 數組解構,必須明確前後順序
    const [left, __, top] = processInput(input);
    
    // good
    function processInput(input) {
      return { left, right, top, bottom };
    }
    // 只需要關註值,而不用關註順序
    const { left, top } = processInput(input);
    

字元串

  • 當需要動態生成字元串時,使用模板字元串而不是字元串拼接:

    // bad
    function sayHi(name) {
      return 'How are you, ' + name + '?';
    }
    
    // bad
    function sayHi(name) {
      return ['How are you, ', name, '?'].join();
    }
    
    
    // good 可讀性比上面更強
    function sayHi(name) {
      return `How are you, ${name}?`;
    }
    
  • 永遠不要使用 eval(),該方法有太多漏洞。

變數

  • 不要使用鏈式變數賦值

因為會產生隱式的全局變數

// bad
(function example() {
  // JavaScript interprets this as
  // let a = ( b = ( c = 1 ) );
  // The let keyword only applies to variable a; variables b and c become
  // global variables.
  let a = b = c = 1;
}());

console.log(a); // throws ReferenceError
// 在塊的外層也訪問到了,代表這是一個全局變數。
console.log(b); // 1 
console.log(c); // 1

// good
(function example() {
  let a = 1;
  let b = a;
  let c = a;
}());

console.log(a); // throws ReferenceError
console.log(b); // throws ReferenceError
console.log(c); // throws ReferenceError

// the same applies for `const`
  • 不要使用一元自增自減運算符(++--

    根據 eslint 文檔,一元增量和減量語句受到自動分號插入的影響,並且可能會導致應用程式中的值遞增或遞減的靜默錯誤。 使用 num + = 1 而不是 num ++num ++ 語句也是含義清晰的。

  // bad

  const array = [1, 2, 3];
  let num = 1;
  num++;
  --num;

  let sum = 0;
  let truthyCount = 0;
  for (let i = 0; i < array.length; i++) {
    let value = array[i];
    sum += value;
    if (value) {
      truthyCount++;
    }
  }

  // good

  const array = [1, 2, 3];
  let num = 1;
  num += 1;
  num -= 1;

  const sum = array.reduce((a, b) => a + b, 0);
  const truthyCount = array.filter(Boolean).length;

屬性

  • 訪問屬性時使用點符號
const luke = {
  jedi: true,
  age: 28,
};

// bad
const isJedi = luke['jedi'];

// good
const isJedi = luke.jedi;
  • 根據表達式訪問屬性時使用[]
const luke = {
  jedi: true,
  age: 28,
};

function getProp(prop) {
  return luke[prop];
}

const isJedi = getProp('je'+'di');

測試

  • 無論用哪個測試框架,都需要寫測試。
  • 儘量去寫很多小而美的函數,減少突變的發生
  • 小心 stub 和 mock —— 這會讓你的測試變得容易出現問題。
  • 100% 測試覆蓋率是我們努力的目標,即便實際上很少達到。
  • 每當你修了一個 bug, 都要儘量寫一個回歸測試。 如果一個 bug 修複了,沒有回歸測試,很可能以後會再次出問題。

公共約束

註釋

  • 多行註釋用 /** ... */
// bad
// make() returns a new element
// based on the passed in tag name
//
// @param {String} tag
// @return {Element} element
function make(tag) {

  // ...

  return element;
}

// good
/**
 * make() returns a new element
 * based on the passed-in tag name
 */
function make(tag) {

  // ...

  return element;
}
  • 單行註釋用 //
// bad
const active = true;  // is current tab

// good
// is current tab
const active = true;

// bad
function getType() {
  console.log('fetching type...');
  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}

// good
function getType() {
  console.log('fetching type...');

  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}

// also good
function getType() {
  // set the default type to 'no type'
  const type = this._type || 'no type';

  return type;
}
  • // FIXME: 給問題註釋,用 // TODO: 去註釋待辦

分號

為什麼?當 JavaScript 遇到沒有分號結尾的一行,它會執行 自動插入分號 這一規則來決定行末是否加分號。如果 JavaScript 在你的斷行里錯誤的插入了分號,就會出現一些古怪的行為。顯式配置代碼檢查去檢查沒有帶分號的地方可以幫助你防止這種錯誤。

// bad - raises exception
const luke = {}
const leia = {}
[luke, leia].forEach((jedi) => jedi.father = 'vader')

// bad - raises exception
const reaction = "No! That’s impossible!"
(async function meanwhileOnTheFalcon() {
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}())

// bad - returns `undefined` instead of the value on the next line - always happens when `return` is on a line by itself because of ASI!
function foo() {
  return
    'search your feelings, you know it to be foo'
}

// good
const luke = {};
const leia = {};
[luke, leia].forEach((jedi) => {
  jedi.father = 'vader';
});

// good
const reaction = "No! That’s impossible!";
(async function meanwhileOnTheFalcon() {
  // handle `leia`, `lando`, `chewie`, `r2`, `c3p0`
  // ...
}());

// good
function foo() {
  return 'search your feelings, you know it to be foo';
}

命名規範

  • export default 導出模塊A,則這個文件名也叫 A.*import 時候的參數也叫 A :
// file 1 contents
class CheckBox {
  // ...
}
export default CheckBox;

// file 2 contents
export default function fortyTwo() { return 42; }

// file 3 contents
export default function insideDirectory() {}

// in some other file
// bad
import CheckBox from './checkBox'; // PascalCase import/export, camelCase filename
import FortyTwo from './FortyTwo'; // PascalCase import/filename, camelCase export
import InsideDirectory from './InsideDirectory'; // PascalCase import/filename, camelCase export

// bad
import CheckBox from './check_box'; // PascalCase import/export, snake_case filename
import forty_two from './forty_two'; // snake_case import/filename, camelCase export
import inside_directory from './inside_directory'; // snake_case import, camelCase export
import index from './inside_directory/index'; // requiring the index file explicitly
import insideDirectory from './insideDirectory/index'; // requiring the index file explicitly

// good
import CheckBox from './CheckBox'; // PascalCase export/import/filename
import fortyTwo from './fortyTwo'; // camelCase export/import/filename
import insideDirectory from './insideDirectory'; // camelCase export/import/directory name/implicit "index"
// ^ supports both insideDirectory.js and insideDirectory/index.js
  • 當你export default一個函數時,函數名用小駝峰,文件名和函數名一致, export 一個結構體/類/單例/函數庫/對象 時用大駝峰。
function makeStyleGuide() {
  // ...
}

export default makeStyleGuide;



const AirbnbStyleGuide = {
  es6: {
  }
};

export default AirbnbStyleGuide;

標準庫

標準庫中包含一些由於歷史原因遺留的工具類

  • Number.isNaN 代替全局的 isNaN:

    // bad
    isNaN('1.2'); // false
    isNaN('1.2.3'); // true
    
    // good
    Number.isNaN('1.2.3'); // false
    Number.isNaN(Number('1.2.3')); // true
    
  • Number.isFinite 代替 isFinite

// bad
isFinite('2e3'); // true

// good
Number.isFinite('2e3'); // false
Number.isFinite(parseInt('2e3', 10)); // true

類與函數

函數

  • 使用命名函數表達式而不是函數聲明

    為什麼?這是因為函數聲明會發生提升,這意味著在一個文件里函數很容易在其被定義之前就被引用了。這樣傷害了代碼可讀性和可維護性。如果你發現一個函數又大又複雜,且這個函數妨礙了這個文件其他部分的理解性,你應當單獨把這個函數提取成一個單獨的模塊。不管這個名字是不是由一個確定的變數推斷出來的,別忘了給表達式清晰的命名(這在現代瀏覽器和類似 babel 編譯器中很常見)。這消除了由匿名函數在錯誤調用棧產生的所有假設。 (討論)

    // bad
    function foo() {
      // ...
    }
    
    // bad
    const foo = function () {
      // ...
    };
    
    // good
    // lexical name distinguished from the variable-referenced invocation(s)
    // 函數表達式名和聲明的函數名是不一樣的
    const short = function longUniqueMoreDescriptiveLexicalFoo() {
      // ...
    };
    
  • 把立即執行函數包裹在圓括弧里:

    立即執行函數:Immediately Invoked Function expression = IIFE。 為什麼?因為這樣使代碼讀起來更清晰(譯者註:我咋不覺得)。 另外,在模塊化世界里,你幾乎用不著 IIFE。

    // immediately-invoked function expression (IIFE)
    ( ()=> {
      console.log('Welcome to the Internet. Please follow me.');
    }() );
    
  • 不要用 arguments 命名參數。他的優先順序高於每個函數作用域自帶的 arguments 對象,這會導致函數自帶的 arguments 值被覆蓋:

    // bad
    function foo(name, options, arguments) {
      // ...
    }
    
    // good
    function foo(name, options, args) {
      // ...
    }
    
  • 用預設參數語法而不是在函數里對參數重新賦值

    // really bad
    function handleThings(opts) {
      // 如果 opts 的值為 false, 它會被賦值為 {}
      // 雖然你想這麼寫,但是這個會帶來一些微妙的 bug。
      opts = opts || {};
      // ...
    }
    
    // still bad
    function handleThings(opts) {
      if (opts === void 0) {
        opts = {};
      }
      // ...
    }
    
    // good
    function handleThings(opts = {}) {
      // ...
    }
    
  • 把預設參數賦值放在最後面

    // bad
    function handleThings(opts = {}, name) {
      // ...
    }
    
    // good
    function handleThings(name, opts = {}) {
      // ...
    }
    
  • 不要修改參數,也不要重新對函數參數賦值:

    容易導致bug,另外重新對參數賦值也會導致優化問題。

    // bad
    function f1(a) {
      a = 1;
      // ...
    }
    
    function f2(a) {
      if (!a) { a = 1; }
      // ...
    }
    
    // good
    function f3(a) {
      const b = a || 1;
      // ...
    }
    
    function f4(a = 1) {
      // ...
    }
    

箭頭函數

  • 當需要使用箭頭函數的時候,使用它,但是不要濫用

    當函數邏輯複雜時,不推薦使用箭頭函數,而是單獨抽出來放在一個函數里。

    // bad
    [1, 2, 3].map(function (x) {
      const y = x + 1;
      return x * y;
    });
    
    // good
    [1, 2, 3].map((x) => {
      const y = x + 1;
      return x * y;
    });
    
  • 避免箭頭函數與比較操作符混淆

    // bad
    const itemHeight = (item) => item.height <= 256 ? item.largeSize : item.smallSize;
    
    // bad
    const itemHeight = (item) => item.height >= 256 ? item.largeSize : item.smallSize;
    
    // good
    const itemHeight = (item) => (item.height <= 256 ? item.largeSize : item.smallSize);
    
    // good
    const itemHeight = (item) => {
      const { height, largeSize, smallSize } = item;
      return height <= 256 ? largeSize : smallSize;
    };
    

類與構造函數

  • 使用class 語法。避免直接操作 prototype

    // bad
    function Queue(contents = []) {
      this.queue = [...contents];
    }
    Queue.prototype.pop = function () {
      const value = this.queue[0];
      this.queue.splice(0, 1);
      return value;
    };
    
    // good
    class Queue {
      constructor(contents = []) {
        this.queue = [...contents];
      }
      pop() {
        const value = this.queue[0];
        this.queue.splice(0, 1);
        return value;
      }
    }
    
    
  • extends 實現繼承:

    為什麼?它是一種內置的方法來繼承原型功能而不破壞 instanceof

    // bad
    const inherits = require('inherits');
    function PeekableQueue(contents) {
      Queue.apply(this, contents);
    }
    inherits(PeekableQueue, Queue);
    PeekableQueue.prototype.peek = function () {
      return this.queue[0];
    }
    
    // good
    class PeekableQueue extends Queue {
      peek() {
        return this.queue[0];
      }
    }
    
  • 方法可以返回 this 來實現鏈式調用

// bad
Jedi.prototype.jump = function () {
  this.jumping = true;
  return true;
};

Jedi.prototype.setHeight = function (height) {
  this.height = height;
};

const luke = new Jedi();
luke.jump(); // => true
luke.setHeight(20); // => undefined

// good
class Jedi {
  jump() {
    this.jumping = true;
    return this;
  }

  setHeight(height) {
    this.height = height;
    return this;
  }
}

const luke = new Jedi();

luke.jump()
  .setHeight(20);
  • 自定義 toString() 方法是可以的,但需要保證它可以正常工作
class Jedi {
  constructor(options = {}) {
    this.name = options.name || 'no name';
  }

  getName() {
    return this.name;
  }

  toString() {
    return `Jedi - ${this.getName()}`;
  }
}
  • 如果沒有特別定義,類有預設的構造方法。一個空的構造函數或只是代表父類的構造函數是不需要寫的。
// bad
class Jedi {
  constructor() {}

  getName() {
    return this.name;
  }
}

// bad
class Rey extends Jedi {
  // 這種構造函數是不需要寫的
  constructor(...args) {
    super(...args);
  }
}

// good
class Rey extends Jedi {
  constructor(...args) {
    super(...args);
    this.name = 'Rey';
  }
}

模塊

  • 使用(import/export)模塊
// bad
const AirbnbStyleGuide = require('./AirbnbStyleGuide');
module.exports = AirbnbStyleGuide.es6;

// ok
import AirbnbStyleGuide from './AirbnbStyleGuide';
export default AirbnbStyleGuide.es6;

// best
import { es6 } from './AirbnbStyleGuide';
export default es6;
  • 不要導出可變的東西:

變化通常都是需要避免,特別是當你要輸出可變的綁定。雖然在某些場景下可能需要這種技術,但總的來說應該導出常量。

// bad
let foo = 3;
export { foo }

// good
const foo = 3;
export { foo }
  • import JavaScript文件不用包含擴展名
// bad
import foo from './foo.js';
import bar from './bar.jsx';
import baz from './baz/index.jsx';

// good
import foo from './foo';
import bar from './bar';
import baz from './baz';

迭代器與生成器

  • 不要用迭代器。使用 JavaScript 高級函數代替 for-infor-of

    用數組的這些迭代方法: map() / every() / filter() / find() / findIndex() / reduce() / some() / ... , 對象的這些方法 Object.keys() / Object.values() / Object.entries() 得到一個數組,就能去遍歷對象。

    const numbers = [1, 2, 3, 4, 5];
    
    // bad
    let sum = 0;
    for (let num of numbers) {
      sum += num;
    }
    sum === 15;
    
    // good
    let sum = 0;
    numbers.forEach((num) => sum += num);
    sum === 15;
    
    // best (use the functional force)
    const sum = numbers.reduce((total, num) => total + num, 0);
    sum === 15;
    
    // bad
    const increasedByOne = [];
    for (let i = 0; i < numbers.length; i++) {
      increasedByOne.push(numbers[i] + 1);
    }
    
        // good
    const increasedByOne = [];
    numbers.forEach((num) => {
      increasedByOne.push(num + 1);
    });
    
    // best (keeping it functional)
    const increasedByOne = numbers.map((num) => num + 1);
    

提升

  • var 聲明會被提前到離他最近的作用域的最前面,但是它的賦值語句並沒有提前。constlet 被賦予了新的概念 暫時性死區 (TDZ)。 重要的是要知道為什麼 typeof 不再安全
// 我們知道這個不會工作,假設沒有定義全局的 notDefined
function example() {
  console.log(notDefined); // => throws a ReferenceError
}

// 在你引用的地方之後聲明一個變數,他會正常輸出是因為變數提升。
// 註意: declaredButNotAssigned 的值 true 沒有被提升。
function example() {
  console.log(declaredButNotAssigned); // => undefined
  var declaredButNotAssigned = true;
}

// 可以寫成如下例子, 二者意義相同。
function example() {
  let declaredButNotAssigned;
  console.log(declaredButNotAssigned); // => undefined
  declaredButNotAssigned = true;
}

// 用 const,let就不一樣了。
function example() {
  console.log(declaredButNotAssigned); // => throws a ReferenceError
  console.log(typeof declaredButNotAssigned); // => throws a ReferenceError
  const declaredButNotAssigned = true;
}
  • 已命名函數表達式提升他的變數名,不是函數名或函數體
function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  superPower(); // => ReferenceError superPower is not defined

  var named = function superPower() {
    console.log('Flying');
  };
}

// 函數名和變數名一樣是也如此。
function example() {
  console.log(named); // => undefined

  named(); // => TypeError named is not a function

  var named = function named() {
    console.log('named');
  };
}

比較運算符與相等

  • ===!== 嚴格比較而不是 ==!=

  • 條件語句,例如if語句使用coercion與tobooleant抽象方法評估它們的表達式,始終遵循這些簡單的規則:

    • Objects evaluate to true
    • Undefined evaluates to false
    • Null evaluates to false
    • Booleans evaluate to the value of the boolean
    • Numbers evaluate to false if +0, -0, or NaN, otherwise true
    • Strings evaluate to false if an empty string '', otherwise true
if ([0] && []) {
  // true
  // an array (even an empty one) is an object, objects will evaluate to true
}
  • 三元表達式不應該嵌套,儘量保持單行表達式
// bad
const foo = maybe1 > maybe2
  ? "bar"
  : value1 > value2 ? "baz" : null;

// better
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2
? 'bar'
  : maybeNull;

// best
const maybeNull = value1 > value2 ? 'baz' : null;

const foo = maybe1 > maybe2 ? 'bar' : maybeNull;

事件

  • 當把數據載荷傳遞給事件時(例如是 DOM 還是像 Backbone 這樣有很多屬性的事件)。這使得後續的貢獻者(程式員)向這個事件添加更多的數據時不用去找或者更新每個處理器。
// bad
$(this).trigger('listingUpdated', listing.id);

// ...

$(this).on('listingUpdated', (e, listingID) => {
  // do something with listingID
});

類型轉換與強制轉換

  • 字元串
// => this.reviewScore = 9;

// bad
const totalScore = new String(this.reviewScore); // typeof totalScore is "object" not "string"

// bad
const totalScore = this.reviewScore + ''; 

// bad
const totalScore = this.reviewScore.toString(); // 不保證返回 string

// good
const totalScore = String(this.reviewScore);
  • 數字: 用 Number 做類型轉換,parseInt 轉換 string 應總是帶上進位位
const inputValue = '4';

// bad
const val = new Number(inputValue);

// bad
const val = +inputValue;

// bad
const val = inputValue >> 0;

// bad
const val = parseInt(inputValue);

// good
const val = Number(inputValue);

// good
const val = parseInt(inputValue, 10);
  • 移位運算要小心

    移位運算對大於 32 位的整數會導致意外行為。Discussion. 最大的 32 位整數是 2,147,483,647:

2147483647 >> 0 //=> 2147483647
2147483648 >> 0 //=> -2147483648
2147483649 >> 0 //=> -2147483647

推薦資源

  • 網站:

    • MDN: 不管你是僅僅開始入門、學過一點基礎或者是個網站開發老手,你都能在這裡找到有用的資源。
    • JS周刊 : 你可以在這裡,接收到JS社區里最新的動態,其他開發者編寫的優秀工具,閱讀優秀的文章。
    • 印記中文 : JS及其前端領域的文檔集合。
  • 書籍(為了尊重作者的版權,下列書籍僅開源書籍提供鏈接):


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 在當今這個數據驅動的時代,各行各業都正經歷著前所未有的變革。伴隨技術的飛速發展,數據倉庫作為企業數據管理與分析的核心,如何更好地發揮作用,助力企業保持業務的敏捷性與成本效益,成為大家關心的焦點問題。本文將通過具體案例分析,展現基於離線開發的數據倉庫轉型落地中的關鍵步驟與實施策略。 一、業務增長迅速, ...
  • 本文介紹如何通過ModelScope魔搭社區中的多模態表徵開源模型進行多模態向量生成,併入庫至向量檢索服務DashVector中進行向量檢索。 ...
  • ​ 本文介紹如何通過模型服務靈積DashScope進行多模態向量生成,併入庫至向量檢索服務DashVector中進行向量檢索。 ...
  • 引言 我叫李慶旺,是Cisco Webex的一名軟體工程師,同時也是Apache DolphinScheduler(以下簡稱DS)的Committer。 在過去的兩年裡,公司基於Apache DolphinScheduler進行了多項持續改進和創新,以更好地適應我們的業務需求。本文將介紹這些改進的具 ...
  • 這段代碼片段是在 Android 應用中使用 VideoView 播放視頻的示例。下麵是對代碼的詳細解析: 代碼解析 findViewById<VideoView>(R.id.vv).apply { setVideoURI("${baseURL}VideoSrc/${o.getString("Src ...
  • ​GSYVideoPlayer是一個國產的移動端視頻播放器,它採用了IJKPlayer、Media3(EXOPlayer)、MediaPlayer、AliPlayer等四種播放器內核,支持彈幕、濾鏡、廣告等多項功能。 GSYVideoPlayer的Github主頁為https://github.co ...
  • 函數柯里化 含義: 可以大概理解為: 將fn(a,b,c)轉換為fn(a)(b)(c) 原函數: function sum(a,b){ return a+b } console.log(sum(1,2)) 柯里化後: function sum(a) { return function (b) { r ...
  • title: 如何在 Nuxt 3 中有效使用 TypeScript date: 2024/9/9 updated: 2024/9/9 author: cmdragon excerpt: 摘要:本文詳細介紹瞭如何在Nuxt 3項目中有效使用TypeScript,包括創建新項目、安裝TypeScrip ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...