前端干貨之JS最佳實踐

持續更新地址 https://wdd.js.org/js-best-pr...

1. 風格

一千個讀者有一千個哈姆雷特,每個人都有自己的code style。我也曾為了要不要加分號給同事鬧個臉紅脖子粗,實際上有必要嗎? 其實JavaScript已經有了比較流行的幾個風格

  • JavaScript Standard Style
  • Google JavaScript Style Guide
  • Airbnb JavaScript Style Guide

我自己使用的是JavaScript Standard Style, 我之所以使用這個,是因為它有一些工具。可以讓你寫完代碼后,一旦保存,就自動幫你把你的風格的代碼修正成標準分割,而不是死記硬背應該怎么寫。看完這個頁面,你就應該立馬愛上JavaScript Standard Style , 如果你用vscode, 恰好你有寫vue, 你想在.vue文件中使用standard風格,那么你需要看看這篇文章

2. 可維護性

很多時候,我們不是從零開始,開發新代碼。而是去維護別人的代碼,以他人的工作成果為基礎。確保自己的代碼可維護,是贈人玫瑰,手留余香的好事。一方面讓別人看的舒服,另一方面也防止自己長時間沒看過自己的代碼,自己都難以理解。

2.1. 什么是可維護代碼

可維護的代碼的一些特征

  • 可理解易于理解代碼的用途
  • 可適應數據的變化,不需要完全重寫代碼
  • 可擴展要考慮未來對核心功能的擴展
  • 可調試給出足夠的信息,讓調試的時候,確定問題所在
  • 不可分割函數的功能要單一,功能粒度不可分割,可復用性增強

2.2. 代碼約定

2.2.1. 可讀性

  • 統一的縮進方式
  • 注釋
  • 空白行

2.2.1.1. 縮進:

  • 一般使用4個空格
  • 不用制表符的原因是它在不同編輯器里顯示效果不同

2.2.1.2. 注釋:哪些地方需要注釋?

  • 函數和方法
  • 大段代碼
  • 復雜的算法
  • hack

2.2.1.3. 空白行:哪些地方需要空白行?

  • 方法之間
  • 方法里的局部變量和第一個語句之間
  • 單行或者多行注釋
  • 方法內衣個邏輯單元之間
// 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. 變量名和函數名

There are only two hard problem in Computer Science cache invalidation and naming things.---Phil Karlton
  • 駝峰式命名
  • 變量名以名詞開頭
  • 方法名以動詞開頭
  • 常量全部大寫
  • 構造函數以大寫字母開頭
  • jQuery對象以"$"符號開頭
  • 自定義事件處理函數以“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添加一個處理聊天事件的函數,一般都是和websocket服務端推送消息相關
App.addMethod('createChat',function(res){App.log(res);
});
// Bad: 此處調用,這里很容易誤以為這個函數是處理創建聊天的邏輯函數
App.createChat();// Good: 
App.addMethod('onCreateChat',function(res){App.log(res);
});
// Good:此處調用
App.onCreateChat();
變量命名不僅僅是一種科學,更是一種藝術。總之,要短小精悍,見名知意。有些名詞可以反應出變量的類型。

2.2.2.1. 變量名

名詞數據類型含義
count, length,size數值
name, title,message字符串
i, j, k用來循環
car,person,student,user對象
success,fail布爾值
payloadpost數據的請求體
method請求方式

2.2.2.2. 函數名

動詞含義
canFunction returns a boolean
hasFunction returns a boolean
isFunction returns a boolean
getFunction returns a nonboolean
set Function is used to save a value

2.2.2.3. 一些與函數名搭配的常用動詞

動詞用法
send發送
resend重發
validate驗證
query查詢
create創建
add添加
delete刪除
remove移除
insert插入
update更新,編輯
copy復制
render渲染
close關閉
open開啟
clear清除
edit編輯
query查詢
on當事件發生
list渲染一個列表,如用戶列表renderUsersList()
content渲染內容,如用戶詳情的頁面 renderUserContent()

2.2.2.4. 接口常用的動詞

對于http請求的最常用的四種方法,get,post,put,delete,有一些常用的名詞與其對應

含義請求方法詞語栗子
增加postcreatecreateUser,createCall
刪除deletedeletedeleteUser
修改putupdateupdateUser,updateProfile
查詢getget,querygetUser,queryUser(無條件查詢使用get,有條件查詢使用query)

2.2.2.5. 學會使用單復數命名函數

函數名含義
getUser()獲取一個用戶,一般是通過唯一的id來獲取
getUsers()獲取一組用戶,一般是通過一些條件來獲取
createUser()創建一個用戶
createUsers()創建一組用戶

2.2.2.6. 常量

var MAX_COUNT = 10;
var URL = "http://www.nczonline.net/";

2.2.2.7. 構造函數

// Good
function Person(name) {this.name = name;
}
Person.prototype.sayName = function() {alert(this.name);
};
var me = new Person("wdd");

2.2.2.8. 底層http請求接口函數

  • 建議使用“_”開頭,例如App._getUsers();而對于接口函數的封裝,例如App.getUsers(),內部邏輯調用App._getUsers();

2.2.3. 文件名

  • 全部使用小寫字母
  • 單詞之間的間隔使用“-”

eg:

app-main.js
app-event.js
app-user-manger.js

2.2.4. 文件歸類

自己寫的js文件最好和引用的一些第三方js分別放置在不同的文件夾下。

2.2.5. 千萬別用alert

alert的缺點

  • 如果你用alert來顯示提醒消息,那么用戶除了點擊alert上的的確定按鈕外,就只能點擊上面的關閉,或者選擇禁止再選擇對話框,除此以外什么都不能操作。
  • 有些瀏覽器如果禁止了alert的選項,那么你的alert是不會顯示的
  • 如果你在try catch語句里使用alert,那么console里將不會輸出錯誤信息,你都沒辦法查看錯誤的詳細原因,以及儲出錯的位置。

更優雅的提醒方式

  • console.log() 普通提示消息
  • console.error() 錯誤提示消息
  • console.info() 信息提示消息
  • console.warn() 警告提示消息

2.3. 松散耦合

  • html文件中盡可能避免寫js語句
  • 盡量避免在js更改某個css類的屬性,而使用更改類的方法
  • 不要在css中寫js的表達式
  • 解耦應用邏輯和事件處理程序

2.3.1. 將應用邏輯和事件處理程序的解耦

//一般事件訂閱的寫法,以jQuery的寫法為栗子
$(document).on('click','#btn-get-users',function(event){event.stopPropagation();//下面的省略號表示執行獲取所有用于并顯示在頁面上的邏輯// Bad.........//
});

如果增加了需求,當點擊另外一個按鈕的時候,也要執行獲取所有用戶并顯示在頁面上,那么上面省略的代碼又要復制一份。如果接口有改動,那么需要在兩個不同的地方都要修改。
所以,應該這樣。

$(document).on('click','#btn-get-users',function(event){event.stopPropagation();//將應用邏輯分離在其他個函數中// GoodApp.getUsers();App.renderUsers();
});

2.3.2. 松散解耦規則

  • 不要將event對象傳給其他方法,只傳遞來自event對象中的某些數據
  • 任何事件處理程序都應該只處理事件,然后把處理轉交給應用邏輯。

2.3.3. 將異步請求和數據處理解耦

// Bad
ReqApi.tenant.queryUsers({},function(res){if(!res.success){console.error(res);return;}//對數據的處理.........
});    

上面代碼對數據的處理直接寫死在異步請求里面,如果換了一個請求,但是數據處理方式是一樣的,那么又要復制一遍數據處理的代碼。最好的方式是將數據處理模塊化成為一個函數。

// Good
ReqApi.tenant.queryUsers({},function(res){if(!res.success){console.error(res);return;}//對數據的處理App.renderUsers(res.data);
}); 

異步請求只處理請求,不處理數據。函數的功能要專一,功能粒度不可分割。

2.3.4. 不要將某個變量寫死在函數中,盡量使用參數傳遞進來

如果你需要一個函數去驗證輸入框是否是空,如下。這種方式就會綁定死了這個只能驗證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. 尊總對象所有權

javascript動態性質是的幾乎任何東西在任何時間都能更改,這樣就很容易覆寫了一些默認的方法。導致一些災難性的后果。如果你不負責或者維護某個對象,那么你就不能對它進行修改。

  • 不要為實例或原型添加屬性
  • 不要為實例或者原型添加方法
  • 不要重定義存已存在的方法

2.4.2. 避免全局變量

// Bad 兩個全局變量
var name = "wdd";
funtion getName(){console.log(name);
}// Good 一個全局變量
var App = {name:"wdd",sayName:funtion(){console.log(this.name);//如果這個函數當做回調數使用,這個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進行比較的代碼,可以用以下技術進行替換

  • 如果值是一個應用類型,使用instanceof操作符,檢查其構造函數
  • 如果值是基本類型,使用typeof檢查其類型
  • 如果是希望對象包含某個特定的方法名,則只用typeof操作符確保指定名字的方法存在于對象上。

代碼中與null比較越少,就越容易確定代碼的目的,消除不必要的錯誤。

2.4.4. 從代碼中分離配置文件

配置數據是一些硬代碼(hardcoded),看下面的栗子

function validate(value){if(!value){alert('Invalid value');location.href = '/errors/invalid.php';}
}

上面代碼里有兩個配置數據,一個是UI字符串('Invalid value'),另一個是一個Url('/error/invalid.php')。如果你把他們寫死在代碼里,那么如果當你需要修改這些地方的時候,那么你必須一處一處的檢查并修改,而且還可能會遺漏。

2.4.4.1. 所以第一步是要區分,哪些代碼應該寫成配置文件的形式?

  • 顯示在UI元素中的字符串
  • URL
  • 一些重復的唯一值
  • 一些設置變量
  • 任何可能改變的值

2.4.4.2. 一些例子

var Config = {"MSG_INVALID_VALUE":"Invalid value","URL_INVALID":"/errors/invalid.php"
}

2.4.5. 調試信息開關

在開發過程中,可能隨處留下幾個console.log,或者alert語句,這些語句在開發過程中是很有價值的。但是項目一旦進入生產環境,過多的console.log可能影響到瀏覽器的運行效率,過多的alert會降低程序的用戶體驗。而我們最好不要在進入生產環境前,一處一處像掃雷一樣刪除或者注釋掉這些調試語句。

最好的方式是設置一個開關。

//全局命令空間
var App = {debug:true,log:function(msg){if(debug){console.log(msg);}},alert:function(msg){if(debug){alert(msg);}}
};//使用
App.log('獲取用戶信息成功');
App.alert('密碼不匹配');//關閉日志輸出與alert
App.debug = false;

2.4.6. 使用jQuery Promise

沒使用promise之前的回調函數寫法

// bad:沒使用promise之前的回調函數寫法
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);}});
}//調用
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();
}//調用
sendRequest(req)
.done(function(){//請求成功...
})
.fail(function(){//請求失敗...
});

2.4.7. 顯示錯誤提醒,不要給后端接口背鍋

假如前端要去接口獲取用戶信息并顯示出來,如果你的請求格式是正確的,但是接口返回400以上的錯誤,你必須通過提醒來告知測試,這個錯誤是接口的返回錯誤,而不是前端的邏輯錯誤。

2.4.8. REST化接口請求

對資源的操作包括獲取、創建、修改和刪除資源,這些操作正好對應HTTP協議提供的GET、POST、PUT和DELETE方法。

對應方式

請求類型接口前綴
GET.get,
POST.create 或者 .get
PUT.update
DELETE.delete

說明

  • 有些接口雖然是獲取某一個資源,但是它使用的卻是POST請求,所以建議使用.get比較好

示例:

// 與用戶相關的接口
App.api.user = {};// 獲取一個用戶: 一般來說是一個指定的Id,例如userId
App.api.user.getUser = function(){...
};// 獲取一組用戶: 一般來說是一些條件,獲取條件下的用戶,篩選符合條件的用戶
App.api.user.getUsers = function(){...
};// 創建一個用戶
App.api.user.createUser = function(){};// 創建一組用戶
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. 選擇正確的方法

  • 優化循環

    • 減值迭代:從最大值開始,在循環中不斷減值的迭代器更加高效
    • 簡化終止條件:由于每次循環過程都會計算終止條件,所以必須保證它盡可能快。也就是避免其他屬性查找
    • 簡化循環體:由于循環體是執行最多的,所以要確保其最大限度地優化。
  • 展開循環
  • 避免雙重解釋:
// **Bad** 某些代碼求值
eval("alert('hello')");// **Bad** 創建新函數
var sayHi = new Function("alert('hello')");// **Bad** 設置超時
setTimeout("alert('hello')");
  • 性能的其他注意事項

    • 原生方法較快
    • switch語句較快:可以適當的替換ifelse語句case 的分支不要超過128條
    • 位運算符較快

3.3. 最小化語句數

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,并用分號結尾。

3.3.2. 插入迭代值

// Good
var name = values[i++];

3.3.3. 使用數組和對象字面量

// Good
var values = ['a','b','c'];var person = {name:'wdd',age:10
};

只要有可能,盡量使用數組和對象字面量的表達式來消除不必要的語句

3.4. 優化DOM交互

在JavaScript各個方面中,DOM無疑是最慢的一部分。DOM操作與交互要消耗大量的時間。因為他們往往需要重新渲染整個頁面或者某一部分。進一步說,看似細微的操作也可能花很久來執行。因為DOM要處理非常多的信息。理解如何優化與DOM的交互可以極大的提高腳本完成的速度。
  • 使用dom緩存技術
  • 最小化現場更新
  • 使用innerHTML插入大段html
  • 使用事件代理

3.4.1. Dom緩存技術

調用頻率非常高的dom查找,可以將DOM緩存在于一個變量中

// 最簡單的dom緩存var domCache = {};function myGetElement(tag){return domCache[tag] = domCache[tag] || $(tag);
}

3.5. 避免過長的屬性查找,設置一個快捷方式

// 先看下面的極端情況
app.user.mother.parent.home.name = 'wdd'
app.user.mother.parent.home.adderess = '上海'
app.user.mother.parent.home.weather = '晴天'// 更優雅的方式
var home = app.user.mother.parent.home;
home.name = 'wdd';
home.address = '上海',
home.weather = '晴天'

注意
使用上面的方式是有前提的,必須保證app.user.mather.parent.home是一個對象,因為對象是傳遞的引用。如果他的類型是一個基本類型,例如:number,string,boolean,那么復制操作僅僅是值傳遞,新定義的home的改變,并不會影響到app.user.mather.parent.home的改變。

4. 快捷方式

4.1. 字符串轉數字

+'4.1' === 4.1

4.2. 數字轉字符

4.1+'' === '4.1'

4.3. 字符串取整

'4.99' | 0 === 4

5. 通用編碼原則

建議讀者自行擴展

  • DRY(dont't repeat yoursele: 不要重復你自己)
  • 高內聚低耦合
  • 開放閉合
  • 最小意外
  • 單一職責(single responsibility)

6. 高級技巧

6.1. 安全類型檢測

  • javascript內置類型檢測并不可靠
  • safari某些版本(<4)typeof正則表達式返回為function

建議使用Object.prototype.toString.call()方法檢測數據類型

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對象形式實現的任何函數,isFunction都返回false,因為他們并非原生的javascript函數。

在web開發中,能夠區分原生與非原生的對象非常重要。只有這樣才能確切知道某個對象是否有哪些功能

以上所有的正確性的前提是:Object.prototype.toString沒有被修改過

6.2. 作用域安全的構造函數

function Person(name){this.name = name;
}//使用new來創建一個對象
var one = new Person('wdd');//直接調用構造函數
Person();

由于this是運行時分配的,如果你使用new來操作,this指向的就是one。如果直接調用構造函數,那么this會指向全局對象window,然后你的代碼就會覆蓋window的原生name。如果有其他地方使用過window.name, 那么你的函數將會埋下一個深藏的bug。

那么,如何才能創建一個作用域安全的構造函數?

function Person(name){if(this instanceof Person){this.name = name;}else{return new Person(name);}
}

6.3. 惰性載入函數

假設有一個方法X,在A類瀏覽器里叫A,在b類瀏覽器里叫B,有些瀏覽器并沒有這個方法,你想實現一個跨瀏覽器的方法。

惰性載入函數的思想是:在函數內部改變函數自身的執行邏輯

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

// 下面代碼在谷歌瀏覽器中執行
> var person = {name: 'wdd'};
undefined
> Object.preventExtensions(person);
Object {name: "wdd"}
> person.age = 10
10
> person
Object {name: "wdd"}
> Object.isExtensible(person)
false

6.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. 凍結對象 Object.freeze

最嚴格的防篡改就是凍結對象。對象不可擴展,而且密封,不能修改。只能訪問。

6.5. 高級定時器

6.5.1. 函數節流

函數節流的思想是:某些代碼不可以沒有間斷的連續重復執行

var processor = {timeoutId: null,// 實際進行處理的方法performProcessing: function(){...},// 初始化調用方法process: function(){clearTimeout(this.timeoutId);var that = this;this.timeoutId = setTimeout(function(){that.performProcessing();}, 100);}
}// 嘗試開始執行
processor.process();

6.5.2. 中央定時器

頁面如果有十個區域要動態顯示當前時間,一般來說,可以用10個定時來實現。其實一個中央定時器就可以搞定。

中央定時器動畫 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. 函數式編程

推薦閱讀:JS函數式編程中文版

8. HTML的告誡

  • 使用input的時候,一定要加上maxlength屬性。(你以為只需要輸入一個名字的地方,用戶可能復制一篇文章放進去。)
  • 從input取值的時候,最好去除一下首尾空格

9. ajax的告誡

ajax在使用的時候,例如點擊按鈕,獲取某個列表。需要注意以下方面

  1. ajax請求還沒有結束時,按鈕一定要disabled,防止多次點擊。請求結束時,才去掉按鈕的disabled屬性。
  2. 請求沒結束的時候,一定要顯示一個gif的動畫,告訴用戶請求還在loading。不要讓用戶以為這垃圾程序又卡死了。
  3. 請求的結果如果是空的,一定要告訴用戶: 很抱歉,暫時沒有查詢到相關記錄之類的話語。不要給一個空白頁面給用戶。
  4. 最好考慮到請求報錯的情況,給出友好的錯誤提醒。

10. 代碼整潔之道

10.1. 函數整潔

  • 盡量將所有代碼封裝在函數中,不要暴露全局變量
  • 每個函數的函數體中,代碼行越少越好,最好一個函數中就一句代碼

11. 工程化與模塊化

11.1. 前端構建工具必不可少

11.1.1. webpack

11.1.2. rollup

11.1.3. parcel

12. 協議 TCP IP HTTP

如果你認為前端不需要關于協議的知識,那么你就是大錯特錯了。其實不僅僅是前端,所有的開發者都應該學習底層的協議。因為他們是互聯網通信的基石。

推薦三本必讀的書籍
  • HTTP權威指南
  • 圖解TCP/IP : 第5版
  • 圖解HTTP

或者你一也可以看看關于協議方面的一些問題,以及如果你遇到過,你是否知道如何解決:

  • 可能被遺漏的https與http的知識點
  • 啞代理 - TCP鏈接高Recv-Q,內存泄露的罪魁禍首

13. 推薦深度閱讀

13.1. 推薦閱讀技術書籍

  • 編寫可讀代碼的藝術
  • 編寫可維護的JavaScript
  • JavaScript忍者秘籍(第2版)
  • JavaScript語言精粹
  • HTTP權威指南
  • 圖解TCP/IP : 第5版
  • 圖解HTTP
  • 代碼整潔之道

13.2. 推薦閱讀在線文章

  • Writing Fast, Memory-Efficient JavaScript
  • JavaScript 秘密花園
  • You-Dont-Know-JS
  • 關于緩存,你應該鏈接的一切
  • JS函數式編程中文版

13.3. 技術之外

  • 筑巢引鳳-高黏度社會化網站設計秘訣
  • 黑客與畫家

14. 參考文獻

  • JavaScript高級程序設計(第3版) 【美】尼古拉斯·澤卡斯
  • Maintainable JavaScript (英文版) Nicholas C. Zakas(其實和上邊那本書應該是同一個人)
  • JavaScript忍者秘籍 John Resig / Bear Bibeault (John Resig 大名鼎鼎jQuery的創造者)
  • 百度前端研發部 文檔與源碼編寫風格
  • js函數式編程指南
  • JavaScript SDK Design Guide: JavaScript-sdk設計指南

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/542476.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/542476.shtml
英文地址,請注明出處:http://en.pswp.cn/news/542476.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

python requests和urllib_Python——深入理解urllib、urllib2及requests(requests不建議使用?)...

深入理解urllib、urllib2及requestsPython 是一種面向對象、解釋型計算機程序設計語言&#xff0c;由Guido vanRossum于1989年底發明&#xff0c;第一個公開發行版發行于1991年&#xff0c;Python 源代碼同樣遵循 GPL(GNU General PublicLicense)協議[1] 。Python語法簡潔而清晰…

ssh查找linux端口,linux – 查找當前連接的端口號SSH

我正在使用SSH連接創建一個本地模擬器(未連接到Internet).我已經開始使用特定范圍的端口號進行sshd,并對一系列設備進行NAT處理.我必須找到當前連接的端口號.OS CentOS 5.5OpenSSH 6.1我做了以下事情.它適用于正常使用(手動用戶).但是當嘗試嚴格的測試(自動化)時,似乎有時找不到…

this.getstate_Java線程類Thread.State getState()方法(帶示例)

this.getstate線程類Thread.State getState() (Thread Class Thread.State getState()) This method is available in package java.lang.Thread.getState(). 軟件包java.lang.Thread.getState()中提供了此方法。 This method is used to return the state of this thread. 此方…

Java資源大全中文版(Awesome最新版)

來源&#xff1a;http://www.cnblogs.com/best/p/5876559.html 目錄 業務流程管理套件字節碼操作集群管理代碼分析編譯器生成工具構建工具外部配置工具約束滿足問題求解程序持續集成CSV解析數據庫數據結構時間日期工具庫依賴注入開發流程增強工具分布式應用分布式數據庫發布文檔…

運用多種設計模式的綜合案例_SpreadJS 純前端表格控件應用案例:表格數據管理平臺...

由某科技公司研發的表格數據管理平臺&#xff0c;是一款面向業務和企業管理系統定制開發的應用平臺&#xff0c;包括類 Excel 設計器、PC應用端和移動應用端等應用模塊。該平臺具備強大的業務配置和集成開發能力&#xff0c;對于企業客戶的信息系統在管理模式、業務流程、表單界…

linux定位哪個進程出發重啟,定位Linux下定位進程被誰KILL

hezhaoaqiang2012-11-09 11:10可以請教你一個問題嗎&#xff1f;關于arm的交叉編譯。我是按照&#xff1a;http://blog.chinaunix.net/uid-27003388-id-3276139.html 去做的&#xff0c;但是走到 四、建立初始編譯器(bootstrap gcc)下面的make install 它提示如下&#xff1a;m…

Java Integer類numberOfLeadingZeros()方法的示例

整數類numberOfLeadingZeros()方法 (Integer class numberOfLeadingZeros() method) numberOfLeadingZeros() method is available in java.lang package. 在java.lang包中提供了numberOfLeadingZeros()方法 。 numberOfLeadingZeros() method is used to returns the number o…

VS中C++ 項目重命名

應該都有過這樣的經歷&#xff0c;在Visual studio中創建解決方案&#xff0c;添加幾個項目進去&#xff0c;然后開始愉快的敲代碼...。寫代碼正歡的時候&#xff0c;卻總是感覺那里有些不舒服&#xff0c;一細看&#xff0c;這項目名稱取的真心挫&#xff0c;修改個吧。直接右…

Java GregorianCalendar getActualMinimum()方法與示例

GregorianCalendar類getActualMinimum()方法 (GregorianCalendar Class getActualMinimum() method) getActualMinimum() method is available in java.util package. getActualMinimum()方法在java.util包中可用。 getActualMinimum() method is used to get the actual minim…

axure9數據統計插件_WMDA:大數據技術棧的綜合實踐

一、概述WMDA是58自主開發的用戶行為分析產品&#xff0c;同時也是一款支持無埋點的數據采集產品&#xff0c;只需要在第一次使用的時候加載一段SDK代碼&#xff0c;即可采集全量、實時的PC、M、APP三端以及小程序的用戶行為數據。同時&#xff0c;為了滿足用戶個性化的數據采集…

Java Collections unmodifiableCollection()方法與示例

集合類unmodifiableCollection()方法 (Collections Class unmodifiableCollection() method) unmodifiableCollection() method is available in java.util package. unmodifiableCollection()方法在java.util包中可用。 unmodifiableCollection() method is used to get an un…

openfoam安裝中出現allmake error_如何更新OpenFOAM的版本?

這是協作翻譯的第四章&#xff0c;翻譯完感覺挺有意思的&#xff0c;分享給大家一起看看。4.更新OpenFOAM版本4.1 版本管理OpenFOAM以兩種不同的方式分發。一種方式是使用Git倉庫下載的倉庫版本。倉庫版本的版本號由附加的x標記&#xff0c;例如 OpenFOAM2.1.x。該版本會經常更…

java 根據類名示例化類_Java類類的requiredAssertionStatus()方法和示例

java 根據類名示例化類類的類requiredAssertionStatus()方法 (Class class desiredAssertionStatus() method) desiredAssertionStatus() method is available in java.lang package. requiredAssertionStatus()方法在java.lang包中可用。 desiredAssertionStatus() method is …

python中計算排列組合的函數_Python實現的排列組合計算操作示例

本文實例講述了Python實現的排列組合計算操作。分享給大家供大家參考&#xff0c;具體如下&#xff1a;1. 調用 scipy 計算排列組合的具體數值>> from scipy.special import comb, perm>> perm(3, 2)6.0>> comb(3, 2)3.02. 調用 itertools 獲取排列組合的全部…

java日歷類add方法_Java日歷setMinimalDaysInFirstWeek()方法與示例

java日歷類add方法日歷類setMinimalDaysInFirstWeek()方法 (Calendar Class setMinimalDaysInFirstWeek() method) setMinimalDaysInFirstWeek() method is available in java.util package. setMinimalDaysInFirstWeek()方法在java.util包中可用。 setMinimalDaysInFirstWeek(…

相同布局在不同手機上顯示不同_不懂響應式,不同尺寸屏幕下的頁面很難達到最佳效果...

讓用戶在不同設備和尺寸的屏幕下看的頁面顯示效果更佳&#xff0c;屏幕空間利用更高&#xff0c;操作體驗更統一&#xff0c;交互方式更符合習慣。本文主要圍繞什么是響應式&#xff0c;如何搭建響應系統&#xff0c;響應式網站解析 三個部分進行闡述&#xff0c;在項目中提前定…

Java ByteArrayInputStream markSupported()方法與示例

ByteArrayInputStream類markSupported()方法 (ByteArrayInputStream Class markSupported() method) markSupported() method is available in java.util package. markSupported()方法在java.util包中可用。 markSupported() method is used to check whether this ByteArrayI…

markdown 流程圖_測試了12款Markdown編輯器,推薦一個最好用的!

有很多喜歡寫博客的小伙伴問我&#xff0c;這個代碼筆記的格式怎么弄的簡潔又好看&#xff0c;雖然csdn里面有Markdown的書寫模式&#xff0c;但是我還是想推薦一款比較好用的寫筆記的編輯器 - Typora。相信很多小伙伴都在使用吧&#xff0c;這個一直是我最喜歡的 markdown 編輯…

小程序 || 語句_C ++條件語句| 查找輸出程序| 套裝2

小程序 || 語句Program 1: 程序1&#xff1a; #include <iostream>#include <stdio.h>using namespace std;int main(){int num 0;num printf("%d ", printf("%d ", printf("ABC")));if (num 2) {cout << "INDIA&quo…

python爬取天氣預報源代碼_python抓取天氣并分析 實例源碼

【實例簡介】Python代碼抓取獲取天氣預報信息源碼講解。這是一個用Python編寫抓取天氣預報的代碼示例&#xff0c;用python寫天氣查詢軟件程序很簡單。這段代碼可以獲取當地的天氣和、任意城市的天氣預報&#xff0c;原理是根據url找到網站截取相應的數據展現。python抓取廣州天…