T之家12月9日消息 微軟對Chromium開源項(xiàng)目非常感興趣,因?yàn)樵擁?xiàng)目對Edge和Chrome都有利。微軟最新的功能請求之一就是希望通過部署Edge HTML風(fēng)格的滾動特性從而讓Chromium的滾動變得更加靈敏。
微軟打算將Impulse樣式(即EdgeHTML樣式)滾動動畫加入到Chromium中,微軟已經(jīng)將該滾動動畫移植到了基于Chromium的Edge瀏覽器的Dev Canary通道中。默認(rèn)情況下,Edge瀏覽器中啟用了脈沖樣式的滾動動畫。對于Chrome,該功能可能會在未來幾天內(nèi)出現(xiàn)在試驗(yàn)版瀏覽器中。
微軟表示,Impulse-style (也就是EdgeHTML-style)滾動動畫將提供更靈敏的滾動體驗(yàn),用戶啟用后鼠標(biāo)滾輪的每個刻度都試圖模仿基于物理的內(nèi)容,內(nèi)容會開始快速移動然后逐漸變慢。換句話說,由于開始時的快速加速,該模式會給人一種更靈敏的感覺。
此外微軟還在推行另一項(xiàng)稱之為“percent-based scrolling”(基于百分比的滾動)的滾動方案,該模式允許瀏覽器將鼠標(biāo)滾輪或者鍵盤滾動解釋為預(yù)期滾動條的百分比。微軟目前正努力將經(jīng)典版Edge瀏覽器的優(yōu)秀特性移植到Chromium平臺上,包括這項(xiàng)基于百分比的滾動方式。
碼必須盡可能的清晰和易讀。
這實(shí)際上是一種編程藝術(shù) —— 以一種正確并且人們易讀的方式編碼來完成一個復(fù)雜的任務(wù)。一個良好的代碼風(fēng)格大大有助于實(shí)現(xiàn)這一點(diǎn)。
下面是一個備忘單,其中列出了一些建議的規(guī)則(詳情請參閱下文):
現(xiàn)在,讓我們詳細(xì)討論一下這些規(guī)則和它們的原因吧。
沒有什么規(guī)則是“必須”的
沒有什么規(guī)則是“刻在石頭上”的。這些是風(fēng)格偏好,而不是宗教教條。
在大多數(shù)的 JavaScript 項(xiàng)目中,花括號以 “Egyptian” 風(fēng)格(譯注:“egyptian” 風(fēng)格又稱 K&R 風(fēng)格 — 代碼段的開括號位于一行的末尾,而不是另起一行的風(fēng)格)書寫,左花括號與相應(yīng)的關(guān)鍵詞在同一行上 — 而不是新起一行。左括號前還應(yīng)該有一個空格,如下所示:
if (condition) {
// do this
// ...and that
// ...and that
}
單行構(gòu)造(如 if (condition) doSomething())也是一個重要的用例。我們是否應(yīng)該使用花括號?如果是,那么在哪里?
下面是這幾種情況的注釋,你可以自己判斷一下它們的可讀性:
對于很短的代碼,寫成一行是可以接受的:例如 if (cond) return null。但是代碼塊(最后一個示例)通常更具可讀性。
沒有人喜歡讀一長串代碼,最好將代碼分割一下。
例如:
// 回勾引號 ` 允許將字符串拆分為多行
let str = `
ECMA International's TC39 is a group of JavaScript developers,
implementers, academics, and more, collaborating with the community
to maintain and evolve the definition of JavaScript.
`;
對于 if 語句:
if (
id === 123 &&
moonPhase === 'Waning Gibbous' &&
zodiacSign === 'Libra'
) {
letTheSorceryBegin();
}
一行代碼的最大長度應(yīng)該在團(tuán)隊(duì)層面上達(dá)成一致。通常是 80 或 120 個字符。
有兩種類型的縮進(jìn):
show(parameters,
aligned, // 5 spaces padding at the left
one,
after,
another
) {
// ...
}
function pow(x, n) {
let result = 1;
// <--
for (let i = 0; i < n; i++) {
result *= x;
}
// <--
return result;
}
插入一個額外的空行有助于使代碼更具可讀性。寫代碼時,不應(yīng)該出現(xiàn)連續(xù)超過 9 行都沒有被垂直分割的代碼。
每一個語句后面都應(yīng)該有一個分號。即使它可以被跳過。
有一些編程語言的分號確實(shí)是可選的,那些語言中也很少使用分號。但是在 JavaScript 中,極少數(shù)情況下,換行符有時不會被解釋為分號,這時代碼就容易出錯。更多內(nèi)容請參閱 代碼結(jié)構(gòu) 一章的內(nèi)容。
如果你是一個有經(jīng)驗(yàn)的 JavaScript 程序員,你可以選擇像 StandardJS 這樣的無分號的代碼風(fēng)格。否則,最好使用分號以避免可能出現(xiàn)的陷阱。大多數(shù)開發(fā)人員都應(yīng)該使用分號。
盡量避免代碼嵌套層級過深。
例如,在循環(huán)中,有時候使用 continue 指令以避免額外的嵌套是一個好主意。
例如,不應(yīng)該像下面這樣添加嵌套的 if 條件:
for (let i = 0; i < 10; i++) {
if (cond) {
... // <- 又一層嵌套
}
}
我們可以這樣寫:
for (let i = 0; i < 10; i++) {
if (!cond) continue;
... // <- 沒有額外的嵌套
} //多用這種風(fēng)格。
使用 if/else 和 return 也可以做類似的事情。
例如,下面的兩個結(jié)構(gòu)是相同的。
第一個:
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
} else {
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
}
第二個:
function pow(x, n) {
if (n < 0) {
alert("Negative 'n' not supported");
return;
}
let result = 1;
for (let i = 0; i < n; i++) {
result *= x;
}
return result;
}
但是第二個更具可讀性,因?yàn)?n < 0 這個“特殊情況”在一開始就被處理了。一旦條件通過檢查,代碼執(zhí)行就可以進(jìn)入到“主”代碼流,而不需要額外的嵌套。
如果你正在寫幾個“輔助”函數(shù)和一些使用它們的代碼,那么有三種方式來組織這些函數(shù)。
// function declarations
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
// the code which uses them
let elem = createElement();
setHandler(elem);
walkAround();
// the code which uses the functions
let elem = createElement();
setHandler(elem);
walkAround();
// --- helper functions ---
function createElement() {
...
}
function setHandler(elem) {
...
}
function walkAround() {
...
}
大多數(shù)情況下,第二種方式更好。
這是因?yàn)殚喿x代碼時,我們首先想要知道的是“它做了什么”。如果代碼先行,那么在整個程序的最開始就展示出了這些信息。之后,可能我們就不需要閱讀這些函數(shù)了,尤其是它們的名字清晰地展示出了它們的功能的時候。
風(fēng)格指南包含了“如果編寫”代碼的通用規(guī)則,例如:使用哪個引號、用多少空格來縮進(jìn)、一行代碼最大長度等非常多的細(xì)節(jié)。
當(dāng)團(tuán)隊(duì)中的所有成員都使用相同的風(fēng)格指南時,代碼看起來將是統(tǒng)一的。無論是團(tuán)隊(duì)中誰寫的,都是一樣的風(fēng)格。
當(dāng)然,一個團(tuán)隊(duì)可以制定他們自己的風(fēng)格指南,但是沒必要這樣做。現(xiàn)在已經(jīng)有了很多制定好的代碼風(fēng)格指南可供選擇。
一些受歡迎的選擇:
如果你是一個初學(xué)者,你可以從本章中上面的內(nèi)容開始。然后你可以瀏覽其他風(fēng)格指南,并選擇一個你最喜歡的。
檢查器(Linters)是可以自動檢查代碼樣式,并提出改進(jìn)建議的工具。
它們的妙處在于進(jìn)行代碼風(fēng)格檢查時,還可以發(fā)現(xiàn)一些代碼錯誤,例如變量或函數(shù)名中的錯別字。因此,即使你不想堅(jiān)持某一種特定的代碼風(fēng)格,我也建議你安裝一個檢查器。
下面是一些最出名的代碼檢查工具:
它們都能夠做好代碼檢查。我使用的是 ESLint。
大多數(shù)檢查器都可以與編輯器集成在一起:只需在編輯器中啟用插件并配置代碼風(fēng)格即可。
例如,要使用 ESLint 你應(yīng)該這樣做:
下面是一個 .eslintrc 文件的例子:
{
"extends": "eslint:recommended",
"env": {
"browser": true,
"node": true,
"es6": true
},
"rules": {
"no-console": 0,
"indent": 2
}
}
這里的 "extends" 指令表示我們是基于 “eslint:recommended” 的設(shè)置項(xiàng)而進(jìn)行設(shè)置的。之后,我們制定我們自己的規(guī)則。
你也可以從網(wǎng)上下載風(fēng)格規(guī)則集并進(jìn)行擴(kuò)展。有關(guān)安裝的更多詳細(xì)信息
此外,某些 IDE 有內(nèi)置的檢查器,這非常方便,但是不像 ESLint 那樣可自定義。
本文描述的(和提到的代碼風(fēng)格指南中的)所有語法規(guī)則,都旨在幫助你提高代碼可讀性。它們都是值得商榷的。
當(dāng)我們思考如何寫“更好”的代碼的時候,我們應(yīng)該問自己的問題是:“什么可以讓代碼可讀性更高,更容易被理解?”和“什么可以幫助我們避免錯誤?”這些是我們討論和選擇代碼風(fēng)格時要牢記的主要原則。
閱讀流行的代碼風(fēng)格指南,可以幫助你了解有關(guān)代碼風(fēng)格的變化趨勢和最佳實(shí)踐的最新想法。
篇文章我們將討論如何將新的語法應(yīng)用在編碼實(shí)踐當(dāng)中,與傳統(tǒng)的 JavaScript 語法結(jié)合在一起,寫出合理的、易于閱讀和維護(hù)的代碼。
所謂"編程風(fēng)格",指的是編寫代碼的規(guī)則。不同的程序員,往往有不同的編程風(fēng)格。而且這里的風(fēng)格包括語法上的編程風(fēng)格和格式上的編程風(fēng)格。
1.ES6 提出了兩個新的聲明變量的命令:let和const。
其中,let完全可以取代var,因?yàn)閮烧哒Z義相同,而且let沒有副作用。
if (true) {
let x = 'hello';
}
for (let y = 0; y <= 10; y++) {
console.log(y);
}
if (true) {
var x = 'hello';//全局變量x
}
for (var y = 0; y <= 10; y++) {//全局變量y
console.log(y);
}
上面代碼如果用var替代let,實(shí)際上就聲明了兩個全局變量,這顯然不是理想的設(shè)計(jì)方式。變量應(yīng)該只在其聲明的代碼塊內(nèi)有效,var命令做不到這一點(diǎn)。
2.var命令存在變量提升效用,let命令沒有這個問題。
if (true) {
console.log(x); // ReferenceError引用錯誤
let x = 'hello';
}
if (true) {
console.log(x); // undefined,變量提升
var x = 'hello';
}
3.在let和const之間,建議優(yōu)先使用const,尤其是在全局環(huán)境,不應(yīng)該設(shè)置變量,應(yīng)設(shè)置常量。原因是const可以提醒閱讀程序的人,這個變量不能改變,比較符合函數(shù)式編程思想,并且JavaScript 編譯器會對const進(jìn)行優(yōu)化,所以多使用const,有利于提高程序的運(yùn)行效率。
//傳統(tǒng)的方式
var a = 1,
b = 2,
c = 3;
//新的方式
const a = 1;
const b = 2;
const c = 3;
//更優(yōu)的方式
const [a, b, c] = [1, 2, 3];
//不建議
const a = "foobar";
const b = 'foo' + a + 'bar';
//建議
const a = 'foobar';
const b = `foo${a}bar`;
ES6允許按照一定模式,從數(shù)組和對象中提取值,對變量進(jìn)行賦值,這被稱為解構(gòu)
使用數(shù)組成員對變量賦值時,優(yōu)先使用解構(gòu)賦值。
const arr = [1, 2, 3, 4];
// 不建議
const first = arr[0];
const second = arr[1];
// 建議
const [first, second] = arr;
函數(shù)的參數(shù)如果是對象的成員,優(yōu)先使用解構(gòu)賦值。
// 不建議
function getFullName(user) {
const firstName = user.firstName;
const lastName = user.lastName;
}
// 建議
function getFullName(obj) {
const { firstName, lastName } = obj;
}
// 建議
function getFullName({ firstName, lastName }) {
}
1.對象的操作
對象盡量靜態(tài)化,一旦定義,就不得隨意添加新的屬性。如果添加屬性不可避免,要使用Object.assign方法。
// 不建議
const a = {};
a.x = 3;
// 建議
const a = {};
Object.assign(a, { x: 3 });
// 或者這樣
const a = { x: null };
a.x = 3;
對象的屬性和方法,盡量采用簡潔表達(dá)法
var ref = 'some value';
// 不推薦
const atom = {
ref: ref,
value: 1,
addValue: function (value) {
return atom.value + value;
},
};
// 推薦
const atom = {
ref,
value: 1,
addValue(value) {
return atom.value + value;
},
};
2.使用擴(kuò)展運(yùn)算符(...)拷貝數(shù)組
let arr1 = [1, 2, 3];
let arr2 = [4, 5, 6];
let arr3 = [7, 8, 9];
console.log(arr1.concat(arr2, arr3)); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
console.log([...arr1, ...arr2, ...arr3]); //[1, 2, 3, 4, 5, 6, 7, 8, 9]
3.立即執(zhí)行函數(shù)可以寫成箭頭函數(shù)的形式。
(() => {
console.log('Welcome to the Internet');
})();
4.用 Class取代prototype 的操作。因?yàn)?Class 的寫法更簡潔,更易于理解。
// 構(gòu)造函數(shù)+原型
function Person(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
this.showinfo = function() {
return this.name;
}
}
Person.prototype.showinfo = function() {
return this.name + this.age + this.sex
}
// class
class Person {
constructor(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
showinfo() {
return this.name
}
}
5.ESLint 的使用
ESLint 是一個語法規(guī)則和代碼風(fēng)格的檢查工具,可以用來保證寫出語法正確、風(fēng)格統(tǒng)一的代碼。
首先,在項(xiàng)目的根目錄安裝 ESLint。
$ npm install --save-dev eslint
然后,安裝 Airbnb 語法規(guī)則,以及 import、a11y、react 插件。
$ npm install --save-dev eslint-config-airbnb
$ npm install --save-dev eslint-plugin-import eslint-plugin-jsx-a11y eslint-plugin-react
最后,在項(xiàng)目的根目錄下新建一個.eslintrc文件,配置 ESLint。
{
"extends": "eslint-config-airbnb"
}
現(xiàn)在就可以檢查,當(dāng)前項(xiàng)目的代碼是否符合預(yù)設(shè)的規(guī)則。
index.js文件的代碼如下。
var unused = 'I have no purpose!';
function greet() {
var message = 'Hello, World!';
console.log(message);
}
greet(); 使用 ESLint 檢查這個文件,就會報(bào)出錯誤。
$ npx eslint index.js
index.js
1:1 error Unexpected var, use let or const instead no-var
1:5 error unused is defined but never used no-unused-vars
4:5 error Expected indentation of 2 characters but found 4 indent
4:5 error Unexpected var, use let or const instead no-var
5:5 error Expected indentation of 2 characters but found 4 indent
? 5 problems (5 errors, 0 warnings)
上面代碼說明,原文件有五個錯誤,其中兩個是不應(yīng)該使用var命令,而要使用let或const;一個是定義了變量,
卻沒有使用;另外兩個是行首縮進(jìn)為 4 個空格,而不是規(guī)定的 2 個空格。
1.大括號的位置
絕大多數(shù)的編程語言,都用大括號({})表示代碼塊。對于起首的大括號的位置,有許多不同的寫法。
最流行的有兩種。
第一種是起首的大括號另起一行 - 推薦
block{
}
第二種是起首的大括號跟在關(guān)鍵字的后面,但是Javascript會自動添加句末的分號,有可能會導(dǎo)致一些難以察覺的錯誤。
//下面的情況就會產(chǎn)生問題。
function fn() {
return
{
key: value
};
}
2.圓括號
圓括號在Javascript中有兩種作用,一種表示調(diào)用函數(shù),另一種表示不同的值的組合。我們可以用空格,區(qū)分這兩
種不同的括號。
調(diào)用函數(shù)的時候,函數(shù)名與左括號之間沒有空格。
function fn(){}
fn()
函數(shù)名與參數(shù)序列之間,沒有空格。
function fn(x,y){
return x + y;
}
fn(1,2)
所有其他語法元素與左括號之間,都有一個空格
if (a === 0){...}
3.分號
分號表示語句的結(jié)束。大多數(shù)情況下,如果你省略了句尾的分號,Javascript會自動添加。
但麻煩的是,如果下一行的第一個符號是下面這五個字符之一,Javascript將不對上一行句尾添加分號:"("、"["、"/"、"+"和"-"。
4.相等和嚴(yán)格相等(恒等)
Javascript有兩個表示"相等"的運(yùn)算符:"相等"(==)和"嚴(yán)格相等"(===)。
因?yàn)?#34;相等"運(yùn)算符會自動轉(zhuǎn)換變量類型(隱式轉(zhuǎn)換),這樣寫會造成很多意想不到的情況。
所有變量聲明都放在函數(shù)的頭部。
所有函數(shù)都在使用之前定義。
*請認(rèn)真填寫需求信息,我們會在24小時內(nèi)與您取得聯(lián)系。