摘要:避免與進行比較避免推薦與進行比較的代碼,可以用以下技術(shù)進行替換如果值是一個應(yīng)用類型,使用操作符,檢查其構(gòu)造函數(shù)如果值是基本類型,使用檢查其類型如果是希望對象包含某個特定的方法名,則只用操作符確保指定名字的方法存在于對象上。
持續(xù)更新地址 https://wdd.js.org/js-best-pr...1. 風(fēng)格
一千個讀者有一千個哈姆雷特,每個人都有自己的code style。我也曾為了要不要加分號給同事鬧個臉紅脖子粗,實際上有必要嗎? 其實JavaScript已經(jīng)有了比較流行的幾個風(fēng)格
JavaScript Standard Style
Google JavaScript Style Guide
Airbnb JavaScript Style Guide
我自己使用的是JavaScript Standard Style, 我之所以使用這個,是因為它有一些工具。可以讓你寫完代碼后,一旦保存,就自動幫你把你的風(fēng)格的代碼修正成標準分割,而不是死記硬背應(yīng)該怎么寫。看完這個頁面,你就應(yīng)該立馬愛上JavaScript Standard Style , 如果你用vscode, 恰好你有寫vue, 你想在.vue文件中使用standard風(fēng)格,那么你需要看看這篇文章
2. 可維護性很多時候,我們不是從零開始,開發(fā)新代碼。而是去維護別人的代碼,以他人的工作成果為基礎(chǔ)。確保自己的代碼可維護,是贈人玫瑰,手留余香的好事。一方面讓別人看的舒服,另一方面也防止自己長時間沒看過自己的代碼,自己都難以理解。2.1. 什么是可維護代碼
可維護的代碼的一些特征
可理解易于理解代碼的用途
可適應(yīng)數(shù)據(jù)的變化,不需要完全重寫代碼
可擴展要考慮未來對核心功能的擴展
可調(diào)試給出足夠的信息,讓調(diào)試的時候,確定問題所在
不可分割函數(shù)的功能要單一,功能粒度不可分割,可復(fù)用性增強
2.2. 代碼約定 2.2.1. 可讀性統(tǒng)一的縮進方式
注釋
空白行
2.2.1.1. 縮進:一般使用4個空格
不用制表符的原因是它在不同編輯器里顯示效果不同
2.2.1.2. 注釋:哪些地方需要注釋?函數(shù)和方法
大段代碼
復(fù)雜的算法
hack
2.2.1.3. 空白行:哪些地方需要空白行?方法之間
方法里的局部變量和第一個語句之間
單行或者多行注釋
方法內(nèi)衣個邏輯單元之間
// Good if (wl && wl.length) { for (i = 0, l = wl.length; i < l; ++i) { p = wl[i]; type = Y.Lang.type(r[p]); if (s.hasOwnProperty(p)) { if (merge && type == "object") { Y.mix(r[p], s[p]); } else if (ov || !(p in r)) { r[p] = s[p]; } } } }2.2.2. 變量名和函數(shù)名
There are only two hard problem in Computer Science cache invalidation and naming things.---Phil Karlton
駝峰式命名
變量名以名詞開頭
方法名以動詞開頭
常量全部大寫
構(gòu)造函數(shù)以大寫字母開頭
jQuery對象以"$"符號開頭
自定義事件處理函數(shù)以“on”開頭
// Good var count = 10; var myName = "wdd"; var found = true; // Bad: Easily confused with functions var getCount = 10; var isFound = true; // Good function getName() { return myName; } // Bad: Easily confused with variable function theName() { return myName; } // Bad: var btnOfSubmit = $("#submit"); // Good: var $btnOfSubmit = $("#submit"); // Bad:給App添加一個處理聊天事件的函數(shù),一般都是和websocket服務(wù)端推送消息相關(guān) App.addMethod("createChat",function(res){ App.log(res); }); // Bad: 此處調(diào)用,這里很容易誤以為這個函數(shù)是處理創(chuàng)建聊天的邏輯函數(shù) App.createChat(); // Good: App.addMethod("onCreateChat",function(res){ App.log(res); }); // Good:此處調(diào)用 App.onCreateChat();
變量命名不僅僅是一種科學(xué),更是一種藝術(shù)。總之,要短小精悍,見名知意。有些名詞可以反應(yīng)出變量的類型。2.2.2.1. 變量名
名詞 | 數(shù)據(jù)類型含義 |
---|---|
count, length,size | 數(shù)值 |
name, title,message | 字符串 |
i, j, k | 用來循環(huán) |
car,person,student,user | 對象 |
success,fail | 布爾值 |
payload | post數(shù)據(jù)的請求體 |
method | 請求方式 |
動詞 | 含義 |
---|---|
can | Function returns a boolean |
has | Function returns a boolean |
is | Function returns a boolean |
get | Function returns a nonboolean |
set | Function is used to save a value |
動詞 | 用法 |
---|---|
send | 發(fā)送 |
resend | 重發(fā) |
validate | 驗證 |
query | 查詢 |
create | 創(chuàng)建 |
add | 添加 |
delete | 刪除 |
remove | 移除 |
insert | 插入 |
update | 更新,編輯 |
copy | 復(fù)制 |
render | 渲染 |
close | 關(guān)閉 |
open | 開啟 |
clear | 清除 |
edit | 編輯 |
query | 查詢 |
on | 當事件發(fā)生 |
list | 渲染一個列表,如用戶列表renderUsersList() |
content | 渲染內(nèi)容,如用戶詳情的頁面 renderUserContent() |
對于http請求的最常用的四種方法,get,post,put,delete,有一些常用的名詞與其對應(yīng)
含義 | 請求方法 | 詞語 | 栗子 |
---|---|---|---|
增加 | post | create | createUser,createCall |
刪除 | delete | delete | deleteUser |
修改 | put | update | updateUser,updateProfile |
查詢 | get | get,query | getUser,queryUser(無條件查詢使用get,有條件查詢使用query) |
函數(shù)名 | 含義 |
---|---|
getUser() | 獲取一個用戶,一般是通過唯一的id來獲取 |
getUsers() | 獲取一組用戶,一般是通過一些條件來獲取 |
createUser() | 創(chuàng)建一個用戶 |
createUsers() | 創(chuàng)建一組用戶 |
var MAX_COUNT = 10; var URL = "http://www.nczonline.net/";2.2.2.7. 構(gòu)造函數(shù)
// Good function Person(name) { this.name = name; } Person.prototype.sayName = function() { alert(this.name); }; var me = new Person("wdd");2.2.2.8. 底層http請求接口函數(shù)
建議使用“_”開頭,例如App._getUsers();而對于接口函數(shù)的封裝,例如App.getUsers(),內(nèi)部邏輯調(diào)用App._getUsers();
2.2.3. 文件名全部使用小寫字母
單詞之間的間隔使用“-”
eg:
app-main.js app-event.js app-user-manger.js2.2.4. 文件歸類
自己寫的js文件最好和引用的一些第三方j(luò)s分別放置在不同的文件夾下。
2.2.5. 千萬別用alertalert的缺點
如果你用alert來顯示提醒消息,那么用戶除了點擊alert上的的確定按鈕外,就只能點擊上面的關(guān)閉,或者選擇禁止再選擇對話框,除此以外什么都不能操作。
有些瀏覽器如果禁止了alert的選項,那么你的alert是不會顯示的
如果你在try catch語句里使用alert,那么console里將不會輸出錯誤信息,你都沒辦法查看錯誤的詳細原因,以及儲出錯的位置。
更優(yōu)雅的提醒方式
console.log() 普通提示消息
console.error() 錯誤提示消息
console.info() 信息提示消息
console.warn() 警告提示消息
2.3. 松散耦合html文件中盡可能避免寫js語句
盡量避免在js更改某個css類的屬性,而使用更改類的方法
不要在css中寫js的表達式
解耦應(yīng)用邏輯和事件處理程序
2.3.1. 將應(yīng)用邏輯和事件處理程序的解耦//一般事件訂閱的寫法,以jQuery的寫法為栗子 $(document).on("click","#btn-get-users",function(event){ event.stopPropagation(); //下面的省略號表示執(zhí)行獲取所有用于并顯示在頁面上的邏輯 // Bad ... ... ... // });
如果增加了需求,當點擊另外一個按鈕的時候,也要執(zhí)行獲取所有用戶并顯示在頁面上,那么上面省略的代碼又要復(fù)制一份。如果接口有改動,那么需要在兩個不同的地方都要修改。
所以,應(yīng)該這樣。
$(document).on("click","#btn-get-users",function(event){ event.stopPropagation(); //將應(yīng)用邏輯分離在其他個函數(shù)中 // Good App.getUsers(); App.renderUsers(); });2.3.2. 松散解耦規(guī)則
不要將event對象傳給其他方法,只傳遞來自event對象中的某些數(shù)據(jù)
任何事件處理程序都應(yīng)該只處理事件,然后把處理轉(zhuǎn)交給應(yīng)用邏輯。
2.3.3. 將異步請求和數(shù)據(jù)處理解耦// Bad ReqApi.tenant.queryUsers({},function(res){ if(!res.success){ console.error(res); return; } //對數(shù)據(jù)的處理 ... ... ... });
上面代碼對數(shù)據(jù)的處理直接寫死在異步請求里面,如果換了一個請求,但是數(shù)據(jù)處理方式是一樣的,那么又要復(fù)制一遍數(shù)據(jù)處理的代碼。最好的方式是將數(shù)據(jù)處理模塊化成為一個函數(shù)。
// Good ReqApi.tenant.queryUsers({},function(res){ if(!res.success){ console.error(res); return; } //對數(shù)據(jù)的處理 App.renderUsers(res.data); });
異步請求只處理請求,不處理數(shù)據(jù)。函數(shù)的功能要專一,功能粒度不可分割。
2.3.4. 不要將某個變量寫死在函數(shù)中,盡量使用參數(shù)傳遞進來如果你需要一個函數(shù)去驗證輸入框是否是空,如下。這種方式就會綁定死了這個只能驗證id為test的輸入框,換成其他的就不行
// bad function checkInputIsEmpty(){ var value = $("#test").val(); if(value){ return true; } else{ return false; } } // good function isEmptyInput(id){ var value = $("#"+id).val(); if(value){ return true; } else{ return false; } }2.4. 編程實踐 2.4.1. 尊總對象所有權(quán)
javascript動態(tài)性質(zhì)是的幾乎任何東西在任何時間都能更改,這樣就很容易覆寫了一些默認的方法。導(dǎo)致一些災(zāi)難性的后果。如果你不負責(zé)或者維護某個對象,那么你就不能對它進行修改。
不要為實例或原型添加屬性
不要為實例或者原型添加方法
不要重定義存已存在的方法
2.4.2. 避免全局變量// Bad 兩個全局變量 var name = "wdd"; funtion getName(){ console.log(name); } // Good 一個全局變量 var App = { name:"wdd", sayName:funtion(){ console.log(this.name);//如果這個函數(shù)當做回調(diào)數(shù)使用,這個this可能指向window, } };
單一的全局變量便是命名空間的概念,例如雅虎的YUI,jQuery的$等。
2.4.3. 避免與null進行比較funtion sortArray(values){ // 避免 if(values != null){ values.sort(comparator); } }
function sortArray(values){ // 推薦 if(values instanceof Array){ values.sort(compartor); } }2.4.3.1. 與null進行比較的代碼,可以用以下技術(shù)進行替換
如果值是一個應(yīng)用類型,使用instanceof操作符,檢查其構(gòu)造函數(shù)
如果值是基本類型,使用typeof檢查其類型
如果是希望對象包含某個特定的方法名,則只用typeof操作符確保指定名字的方法存在于對象上。
代碼中與null比較越少,就越容易確定代碼的目的,消除不必要的錯誤。
2.4.4. 從代碼中分離配置文件配置數(shù)據(jù)是一些硬代碼(hardcoded),看下面的栗子
function validate(value){ if(!value){ alert("Invalid value"); location.href = "/errors/invalid.php"; } }
上面代碼里有兩個配置數(shù)據(jù),一個是UI字符串("Invalid value"),另一個是一個Url("/error/invalid.php")。如果你把他們寫死在代碼里,那么如果當你需要修改這些地方的時候,那么你必須一處一處的檢查并修改,而且還可能會遺漏。
2.4.4.1. 所以第一步是要區(qū)分,哪些代碼應(yīng)該寫成配置文件的形式?顯示在UI元素中的字符串
URL
一些重復(fù)的唯一值
一些設(shè)置變量
任何可能改變的值
2.4.4.2. 一些例子var Config = { "MSG_INVALID_VALUE":"Invalid value", "URL_INVALID":"/errors/invalid.php" }2.4.5. 調(diào)試信息開關(guān)
在開發(fā)過程中,可能隨處留下幾個console.log,或者alert語句,這些語句在開發(fā)過程中是很有價值的。但是項目一旦進入生產(chǎn)環(huán)境,過多的console.log可能影響到瀏覽器的運行效率,過多的alert會降低程序的用戶體驗。而我們最好不要在進入生產(chǎn)環(huán)境前,一處一處像掃雷一樣刪除或者注釋掉這些調(diào)試語句。
最好的方式是設(shè)置一個開關(guān)。
//全局命令空間 var App = { debug:true, log:function(msg){ if(debug){ console.log(msg); } }, alert:function(msg){ if(debug){ alert(msg); } } }; //使用 App.log("獲取用戶信息成功"); App.alert("密碼不匹配"); //關(guān)閉日志輸出與alert App.debug = false;2.4.6. 使用jQuery Promise
沒使用promise之前的回調(diào)函數(shù)寫法
// bad:沒使用promise之前的回調(diào)函數(shù)寫法 function sendRequest(req,successCallback,errorCallback){ var inputData = req.data || {}; inputData = JSON.stringify(inputData); $.ajax({ url:req.base+req.destination, type:req.type || "get", headers:{ sessionId:session.id }, data:inputData, dataType:"json", contentType : "application/json; charset=UTF-8", success:function(data){ successCallback(data); }, error:function(data){ console.error(data); errorCallback(data); } }); } //調(diào)用 sendRequest(req,function(res){ ... },function(res){ ... });
使用promise之后
function sendRequest(req){ var dfd = $.Deferred(); var inputData = req.data || {}; inputData = JSON.stringify(inputData); $.ajax({ url:req.base+req.destination, type:req.type || "get", headers:{ sessionId:session.id }, data:inputData, dataType:"json", contentType : "application/json; charset=UTF-8", success:function(data){ dfd.resolve(data); }, error:function(data){ dfd.reject(data); } }); return dfd.promise(); } //調(diào)用 sendRequest(req) .done(function(){ //請求成功 ... }) .fail(function(){ //請求失敗 ... });2.4.7. 顯示錯誤提醒,不要給后端接口背鍋
假如前端要去接口獲取用戶信息并顯示出來,如果你的請求格式是正確的,但是接口返回400以上的錯誤,你必須通過提醒來告知測試,這個錯誤是接口的返回錯誤,而不是前端的邏輯錯誤。
2.4.8. REST化接口請求對資源的操作包括獲取、創(chuàng)建、修改和刪除資源,這些操作正好對應(yīng)HTTP協(xié)議提供的GET、POST、PUT和DELETE方法。
對應(yīng)方式
請求類型 | 接口前綴 |
---|---|
GET | .get, |
POST | .create 或者 .get |
PUT | .update |
DELETE | .delete |
說明
有些接口雖然是獲取某一個資源,但是它使用的卻是POST請求,所以建議使用.get比較好
示例:
// 與用戶相關(guān)的接口 App.api.user = {}; // 獲取一個用戶: 一般來說是一個指定的Id,例如userId App.api.user.getUser = function(){ ... }; // 獲取一組用戶: 一般來說是一些條件,獲取條件下的用戶,篩選符合條件的用戶 App.api.user.getUsers = function(){ ... }; // 創(chuàng)建一個用戶 App.api.user.createUser = function(){ }; // 創(chuàng)建一組用戶 App.api.user.createUsers = function(){ }; // 更新一個用戶 App.api.user.updateUser = function(){ }; // 更新一組用戶 App.api.user.updateUsers = function(){ }; // 更新一個用戶 App.api.user.updateUser = function(){ }; // 更新一組用戶 App.api.user.updateUsers = function(){ }; // 刪除一個用戶 App.api.user.deleteUser = function(){ }; // 刪除一組用戶 App.api.user.deleteUsers = function(){ };3. 性能 3.1. 注意作用域
避免全局查找
避免with語句
3.2. 選擇正確的方法
優(yōu)化循環(huán)
減值迭代:從最大值開始,在循環(huán)中不斷減值的迭代器更加高效
簡化終止條件:由于每次循環(huán)過程都會計算終止條件,所以必須保證它盡可能快。也就是避免其他屬性查找
簡化循環(huán)體:由于循環(huán)體是執(zhí)行最多的,所以要確保其最大限度地優(yōu)化。
展開循環(huán)
避免雙重解釋:
// **Bad** 某些代碼求值 eval("alert("hello")"); // **Bad** 創(chuàng)建新函數(shù) var sayHi = new Function("alert("hello")"); // **Bad** 設(shè)置超時 setTimeout("alert("hello")");
性能的其他注意事項
原生方法較快
switch語句較快:可以適當?shù)奶鎿Qifelse語句case 的分支不要超過128條
位運算符較快
3.3. 最小化語句數(shù) 3.3.1. 多個變量聲明(廢棄)// 方式1:Bad var count = 5; var name = "wdd"; var sex = "male"; var age = 10; // 方式2:Good var count = 5, name = "wdd", sex = "male", age = 10;
2017-03-07 理論上方式2可能要比方式1性能高一點。但是我在實際使用中,這個快一點幾乎是沒什么感受的。就像你無法感受到小草的生長一樣。反而可讀性更為重要。所以,每行最好只定義一個變量,并且每行都有一個var,并用分號結(jié)尾。
3.3.2. 插入迭代值// Good var name = values[i++];3.3.3. 使用數(shù)組和對象字面量
// Good var values = ["a","b","c"]; var person = { name:"wdd", age:10 };
只要有可能,盡量使用數(shù)組和對象字面量的表達式來消除不必要的語句
3.4. 優(yōu)化DOM交互在JavaScript各個方面中,DOM無疑是最慢的一部分。DOM操作與交互要消耗大量的時間。因為他們往往需要重新渲染整個頁面或者某一部分。進一步說,看似細微的操作也可能花很久來執(zhí)行。因為DOM要處理非常多的信息。理解如何優(yōu)化與DOM的交互可以極大的提高腳本完成的速度。
使用dom緩存技術(shù)
最小化現(xiàn)場更新
使用innerHTML插入大段html
使用事件代理
3.4.1. Dom緩存技術(shù)調(diào)用頻率非常高的dom查找,可以將DOM緩存在于一個變量中
// 最簡單的dom緩存 var domCache = {}; function myGetElement(tag){ return domCache[tag] = domCache[tag] || $(tag); }3.5. 避免過長的屬性查找,設(shè)置一個快捷方式
// 先看下面的極端情況 app.user.mother.parent.home.name = "wdd" app.user.mother.parent.home.adderess = "上海" app.user.mother.parent.home.weather = "晴天" // 更優(yōu)雅的方式 var home = app.user.mother.parent.home; home.name = "wdd"; home.address = "上海", home.weather = "晴天"
注意
使用上面的方式是有前提的,必須保證app.user.mather.parent.home是一個對象,因為對象是傳遞的引用。如果他的類型是一個基本類型,例如:number,string,boolean,那么復(fù)制操作僅僅是值傳遞,新定義的home的改變,并不會影響到app.user.mather.parent.home的改變。
+"4.1" === 4.14.2. 數(shù)字轉(zhuǎn)字符
4.1+"" === "4.1"4.3. 字符串取整
"4.99" | 0 === 45. 通用編碼原則
建議讀者自行擴展
DRY(dont"t repeat yoursele: 不要重復(fù)你自己)
高內(nèi)聚低耦合
開放閉合
最小意外
單一職責(zé)(single responsibility)
6. 高級技巧 6.1. 安全類型檢測javascript內(nèi)置類型檢測并不可靠
safari某些版本(<4)typeof正則表達式返回為function
建議使用Object.prototype.toString.call()方法檢測數(shù)據(jù)類型
function isArray(value){ return Object.prototype.toString.call(value) === "[object Array]"; } function isFunction(value){ return Object.prototype.toString.call(value) === "[object Function]"; } function isRegExp(value){ return Object.prototype.toString.call(value) === "[object RegExp]"; } function isNativeJSON(){ return window.JSON && Object.prototype.toString.call(JSON) === "[object JSON]"; }
對于ie中一COM對象形式實現(xiàn)的任何函數(shù),isFunction都返回false,因為他們并非原生的javascript函數(shù)。
在web開發(fā)中,能夠區(qū)分原生與非原生的對象非常重要。只有這樣才能確切知道某個對象是否有哪些功能
以上所有的正確性的前提是:Object.prototype.toString沒有被修改過
6.2. 作用域安全的構(gòu)造函數(shù)function Person(name){ this.name = name; } //使用new來創(chuàng)建一個對象 var one = new Person("wdd"); //直接調(diào)用構(gòu)造函數(shù) Person();
由于this是運行時分配的,如果你使用new來操作,this指向的就是one。如果直接調(diào)用構(gòu)造函數(shù),那么this會指向全局對象window,然后你的代碼就會覆蓋window的原生name。如果有其他地方使用過window.name, 那么你的函數(shù)將會埋下一個深藏的bug。
那么,如何才能創(chuàng)建一個作用域安全的構(gòu)造函數(shù)?
function Person(name){ if(this instanceof Person){ this.name = name; } else{ return new Person(name); } }6.3. 惰性載入函數(shù)
假設(shè)有一個方法X,在A類瀏覽器里叫A,在b類瀏覽器里叫B,有些瀏覽器并沒有這個方法,你想實現(xiàn)一個跨瀏覽器的方法。
惰性載入函數(shù)的思想是:在函數(shù)內(nèi)部改變函數(shù)自身的執(zhí)行邏輯
function X(){ if(A){ return new A(); } else{ if(B){ return new B(); } else{ throw new Error("no A or B"); } } }
換一種寫法
function X(){ if(A){ X = function(){ return new A(); }; } else{ if(B){ X = function(){ return new B(); }; } else{ throw new Error("no A or B"); } } return new X(); }6.4. 防篡改對象 6.4.1. 不可擴展對象 Object.preventExtensions
// 下面代碼在谷歌瀏覽器中執(zhí)行 > var person = {name: "wdd"}; undefined > Object.preventExtensions(person); Object {name: "wdd"} > person.age = 10 10 > person Object {name: "wdd"} > Object.isExtensible(person) false6.4.2. 密封對象Object.seal
密封對象不可擴展,并且不能刪除對象的屬性或者方法。但是屬性值可以修改。
> var one = {name: "hihi"} undefined > Object.seal(one) Object {name: "hihi"} > one.age = 12 12 > one Object {name: "hihi"} > delete one.name false > one Object {name: "hihi"}6.4.3. 凍結(jié)對象 Object.freeze
最嚴格的防篡改就是凍結(jié)對象。對象不可擴展,而且密封,不能修改。只能訪問。
6.5. 高級定時器 6.5.1. 函數(shù)節(jié)流函數(shù)節(jié)流的思想是:某些代碼不可以沒有間斷的連續(xù)重復(fù)執(zhí)行
var processor = { timeoutId: null, // 實際進行處理的方法 performProcessing: function(){ ... }, // 初始化調(diào)用方法 process: function(){ clearTimeout(this.timeoutId); var that = this; this.timeoutId = setTimeout(function(){ that.performProcessing(); }, 100); } } // 嘗試開始執(zhí)行 processor.process();6.5.2. 中央定時器
頁面如果有十個區(qū)域要動態(tài)顯示當前時間,一般來說,可以用10個定時來實現(xiàn)。其實一個中央定時器就可以搞定。
中央定時器動畫 demo地址:http://wangduanduan.coding.me...
var timers = { timerId: 0, timers: [], add: function(fn){ this.timers.push(fn); }, start: function(){ if(this.timerId){ return; } (function runNext(){ if(timers.timers.length > 0){ for(var i=0; i < timers.timers.length ; i++){ if(timers.timers[i]() === false){ timers.timers.splice(i, 1); i--; } } timers.timerId = setTimeout(runNext, 16); } })(); }, stop: function(){ clearTimeout(timers.timerId); this.timerId = 0; } };7. 函數(shù)式編程
推薦閱讀:JS函數(shù)式編程中文版
8. HTML的告誡使用input的時候,一定要加上maxlength屬性。(你以為只需要輸入一個名字的地方,用戶可能復(fù)制一篇文章放進去。)
從input取值的時候,最好去除一下首尾空格
9. ajax的告誡ajax在使用的時候,例如點擊按鈕,獲取某個列表。需要注意以下方面
ajax請求還沒有結(jié)束時,按鈕一定要disabled,防止多次點擊。請求結(jié)束時,才去掉按鈕的disabled屬性。
請求沒結(jié)束的時候,一定要顯示一個gif的動畫,告訴用戶請求還在loading。不要讓用戶以為這垃圾程序又卡死了。
請求的結(jié)果如果是空的,一定要告訴用戶: 很抱歉,暫時沒有查詢到相關(guān)記錄之類的話語。不要給一個空白頁面給用戶。
最好考慮到請求報錯的情況,給出友好的錯誤提醒。
10. 代碼整潔之道 10.1. 函數(shù)整潔盡量將所有代碼封裝在函數(shù)中,不要暴露全局變量
每個函數(shù)的函數(shù)體中,代碼行越少越好,最好一個函數(shù)中就一句代碼
11. 工程化與模塊化 11.1. 前端構(gòu)建工具必不可少 11.1.1. webpack 11.1.2. rollup 11.1.3. parcel 12. 協(xié)議 TCP IP HTTP如果你認為前端不需要關(guān)于協(xié)議的知識,那么你就是大錯特錯了。其實不僅僅是前端,所有的開發(fā)者都應(yīng)該學(xué)習(xí)底層的協(xié)議。因為他們是互聯(lián)網(wǎng)通信的基石。
推薦三本必讀的書籍
HTTP權(quán)威指南
圖解TCP/IP : 第5版
圖解HTTP
或者你一也可以看看關(guān)于協(xié)議方面的一些問題,以及如果你遇到過,你是否知道如何解決:
可能被遺漏的https與http的知識點
啞代理 - TCP鏈接高Recv-Q,內(nèi)存泄露的罪魁禍首
13. 推薦深度閱讀 13.1. 推薦閱讀技術(shù)書籍編寫可讀代碼的藝術(shù)
編寫可維護的JavaScript
JavaScript忍者秘籍(第2版)
JavaScript語言精粹
HTTP權(quán)威指南
圖解TCP/IP : 第5版
圖解HTTP
代碼整潔之道
13.2. 推薦閱讀在線文章Writing Fast, Memory-Efficient JavaScript
JavaScript 秘密花園
You-Dont-Know-JS
關(guān)于緩存,你應(yīng)該鏈接的一切
JS函數(shù)式編程中文版
13.3. 技術(shù)之外筑巢引鳳-高黏度社會化網(wǎng)站設(shè)計秘訣
黑客與畫家
14. 參考文獻JavaScript高級程序設(shè)計(第3版) 【美】尼古拉斯·澤卡斯
Maintainable JavaScript (英文版) Nicholas C. Zakas(其實和上邊那本書應(yīng)該是同一個人)
JavaScript忍者秘籍 John Resig / Bear Bibeault (John Resig 大名鼎鼎jQuery的創(chuàng)造者)
百度前端研發(fā)部 文檔與源碼編寫風(fēng)格
js函數(shù)式編程指南
JavaScript SDK Design Guide: JavaScript-sdk設(shè)計指南
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/87943.html
摘要:前言月份開始出沒社區(qū),現(xiàn)在差不多月了,按照工作的說法,就是差不多過了三個月的試用期,準備轉(zhuǎn)正了一般來說,差不多到了轉(zhuǎn)正的時候,會進行總結(jié)或者分享會議那么今天我就把看過的一些學(xué)習(xí)資源主要是博客,博文推薦分享給大家。 1.前言 6月份開始出沒社區(qū),現(xiàn)在差不多9月了,按照工作的說法,就是差不多過了三個月的試用期,準備轉(zhuǎn)正了!一般來說,差不多到了轉(zhuǎn)正的時候,會進行總結(jié)或者分享會議!那么今天我就...
摘要:哪吒別人的看法都是狗屁,你是誰只有你自己說了才算,這是爹教我的道理。哪吒去他個鳥命我命由我,不由天是魔是仙,我自己決定哪吒白白搭上一條人命,你傻不傻敖丙不傻誰和你做朋友太乙真人人是否能夠改變命運,我不曉得。我只曉得,不認命是哪吒的命。 showImg(https://segmentfault.com/img/bVbwiGL?w=900&h=378); 出處 查看github最新的Vue...
閱讀 909·2021-09-09 09:32
閱讀 2849·2021-09-02 10:20
閱讀 2685·2021-07-23 11:24
閱讀 824·2019-08-30 15:54
閱讀 3631·2019-08-30 15:54
閱讀 1346·2019-08-30 11:02
閱讀 2844·2019-08-26 17:40
閱讀 1122·2019-08-26 13:55