本文將根據實踐經驗說明python中使用requests庫編寫爬蟲程序時,出現【中文亂碼】的原因及解決辦法。
首先,本文的【中文亂碼】情況,指的是原網頁中的中文內容在使用requests獲取后,中文完全無法識別的情況,區別于\x、\u等編碼情況。如下圖中的例子:
導致上圖中【中文亂碼】的原因:
使用requests庫時,選擇使用的文本響應方法不合適,且沒有在代碼中添加設置合適的編碼,以致于使用【response.text】自動獲取到的網頁編碼,與實際網頁的編碼不一致,進而產生【中文亂碼】。
使用requests庫時,可能已經形成了一個習慣,常用【response.text】進行文本響應,而【response.content】常用于圖片、視頻等。
這兩者,最大的一個區別就是:
1、【response.text】會自動根據HTTP頭部去推測網頁的編碼,解碼并返回解碼后的文本。
2、【response.content】不會解碼,直接以二進制形式返回。
兩種文本響應方法,如下表:
response.text | 服務器響應的內容,會自動根據響應頭部的字符編碼進行解碼。根據HTTP頭部對響應的編碼做出有根據的推測,推測文本編碼。返回類型:str;常用于:響應文本 |
response.content | 字節方式的響應體,不會根據HTTP頭部對響應的編碼做出有根據的推測。返回類型:bytes(二進制);常用于:圖片、視頻 |
最有效的解決方法:
使用response的encoding、apparent_encoding,得到網頁編碼。
encoding、apparent_encoding兩者最大的區別:
encoding是從header中去提取,而apparent_encoding是從網頁源碼去解析,apparent_encoding得到的結果更準確。
詳細如下表:
response.encoding | 從網頁響應的header中,提取charset字段中的編碼。若header中沒有charset字段,則默認為ISO-8859-1編碼模式,ISO-8859-1編碼無法解析中文,這也是中文亂碼的原因。 |
response.apparent_encoding | 從網頁的內容中(html源碼)中分析網頁編碼的方式。所以apparent_encoding比encoding更加準確,獲取到的才是原網頁的實際編碼。 |
print(response.apparent_encoding)
print(response.encoding)
使用encoding、apparent_encoding兩種方法,所得的結果是不一致的,apparent_encoding才是原網頁實際編碼。如下圖
根據上述方法,獲得原網頁的實際編碼后,手動在代碼中指定文本編碼格式,即可解決【中文亂碼】問題。如下圖:
response.encoding=response.apparent_encoding
以上就是使用requests爬蟲解決中文亂碼的方法,如那位老師有更好的方法還望賜教,謝謝!
符串作為基本的信息交流的橋梁,幾乎被所有的編程語言所實現(然而c、c++沒有提供)。多數開發者幾乎每天都在和字符串打交道,語言內置的String模塊,極大地提升了開發者的效率。JavaScript通過自動裝箱字符串字面量為String對象,自然地繼承了String.prototype的所有方法,更加簡化了字符串的使用。
截止ES6,字符串共包含31個標準的API方法,其中有些方法出鏡率較高,需要摸透原理;有些方法之間相似度較高,需要仔細分辨;甚至有些方法執行效率較低,應當盡量少的使用。下面將從String構造器方法說起,逐步幫助你掌握字符串
String構造器方法
fromCharCode
fromCharCode() 方法返回使用指定的Unicode序列創建的字符串,也就是說傳入Unicode序列,返回基于此創建的字符串。
語法:fromCharCode(num1, num2,…),傳入的參數均為數字。
如下這是一個簡單的例子,將返回 ABC、abc、*、+、- 和 /:
String.fromCharCode(65, 66, 67); // "ABC" String.fromCharCode(97, 98, 99); // "abc" String.fromCharCode(42); // "*" String.fromCharCode(43); // "+" String.fromCharCode(45); // "-" String.fromCharCode(47); // "/"
看起來fromCharCode像是滿足了需求,但實際上由于js語言設計時的先天不足(只能處理UCS-2編碼,即所有字符都是2個字節,無法處理4字節字符),通過該方法并不能返回一個4字節的字符,為了彌補這個缺陷,ES6新增了fromCodePoint方法
fromCodePoint(ES6)
fromCodePoint() 方法基于ECMAScript 2015(ES6)規范,作用和語法同fromCharCode方法,該方法主要擴展了對4字節字符的支持。
// "" 是一個4字節字符,我們先看下它的數字形式 "".codePointAt(); // 119558 //調用fromCharCode解析之,返回亂碼 String.fromCharCode(119558); // "?" //調用fromCodePoint解析之,正常解析 String.fromCodePoint(119558); // ""
除了擴展對4字節的支持外,fromCodePoint還規范了錯誤處理,只要是無效的Unicode編碼,就會拋出錯誤RangeError: Invalid code point...,這就意味著,只要不是符合Unicode字符范圍的正整數(Unicode最多可容納1114112個碼位),均會拋出錯誤,而String.fromCharCode()均返回空字符串
String.fromCodePoint('abc'); // RangeError: Invalid code point NaN String.fromCodePoint(Infinity); // RangeError: Invalid code point Infinity String.fromCodePoint(-1.23); // RangeError: Invalid code point -1.23
raw(ES6)
raw() 方法基于ECMAScript 2015(ES6)規范,它是一個模板字符串的標簽函數,作用類似于Python的r和C#的@字符串前綴,都是用來獲取一個模板字符串的原始字面量。
語法: String.raw(callSite, …substitutions),callSite即模板字符串的『調用點對象』,…substitutions表示任意個內插表達式對應的值,這里理解起來相當拗口,下面我將通俗的講解它。
// 防止特殊字符串被轉義 String.raw`a\nb\tc`; // 輸出為 "a\nb\tc" // 支持內插表達式 let name="louis"; String.raw`Hello \n ${name}`; // "Hello \n louis" // 內插表達式還可以運算 String.raw`1+2=${1+2},2*3=${2*3}`; // "1+2=3,2*3=6" // 對象的raw屬性值為字符串時,從第二個參數起,它們分別被插入到下標為0,1,2,...n的元素后面 String.raw({raw: 'abcd'}, 1, 2, 3); // "a1b2c3d" // 對象的raw屬性值為數組時,從第二個參數起,它們分別被插入到數組下標為0,1,2,...n的元素后面 String.raw({raw: ['a', 'b', 'c', 'd']}, 1, 2, 3); // "a1b2c3d"
那么怎么解釋String.raw函數按照下標挨個去插入的特性呢?
In most cases, String.raw() is used with template strings. The first syntax mentioned above is only rarely used, because the JavaScript engine will call this with proper arguments for you, just like with other tag functions.
這意味著,String.raw作為函數調用時,基本與ES6的tag標簽模板一樣
// 如下是tag函數的實現 function tag(){ const array=arguments[0]; return array.reduce((p, v, i)=> p + (arguments[i] || '') + v); } // 回顧一個simple的tag標簽模板 tag`Hello ${ 2 + 3 } world ${ 2 * 3 }`; // "Hello 5 world 6" // 其實就想當于如下調用 tag(['Hello ', ' world ', ''], 5, 6); // "Hello 5 world 6"
因此String.raw作為函數調用時,不論對象的raw屬性值是字符串還是數組,插槽都是天生的,下標為0,1,2,…n的元素后面都是插槽(不包括最后一個元素)。實際上,它相當于是這樣的tag函數:
function tag(){ const array=arguments[0].raw; if(array===undefined || array===null){ // 這里可簡寫成 array==undefined throw new TypeError('Cannot convert undefined or null to object'); } return array.reduce((p, v, i)=> p + (arguments[i] || '') + v); }
實際上,String.raw作為函數調用時,若第一個參數不是一個符合標準格式的對象,執行將拋出TypeError錯誤。
String.raw({123: 'abcd'}, 1, 2, 3); // TypeError: Cannot convert undefined or null to object
String.prototype
和其他所有對象一樣,字符串實例的所有方法均來自String.prototype。以下是它的屬性特性:
writable: false
enumerable: false
configurable: false
可見,字符串屬性不可編輯,任何試圖改變它屬性的行為都將拋出錯誤。
屬性
String.prototype共有兩個屬性,如下:
方法
字符串原型方法分為兩種,一種是html無關的方法,一種是html有關的方法。我們先看第一種。但是無論字符串方法如何厲害,都不至于強大到可以改變原字符串。
常用的方法有,charAt、charCodeAt、concat、indexOf、lastIndexOf、localeCompare、match、replace、search、slice、split、substr、substring、toLocaleLowerCase、toLocaleUpperCase、toLowerCase、toString、toUpperCase、trim、valueof 等ES5支持的,以及 codePointAt、contains、endsWith、normalize、repeat、startsWith 等ES6支持的,還包括 quote、toSource、trimLeft、trimRight 等非標準的。
接下來我們將對各個方法分別舉例闡述其用法。若沒有特別說明,默認該方法兼容所有目前主流瀏覽器。
charAt
charAt() 方法返回字符串中指定位置的字符。
語法:str.charAt(index)
index 為字符串索引(取值從0至length-1),如果超出該范圍,則返回空串
console.log("Hello, World".charAt(8)); // o, 返回下標為8的字符串o
charCodeAt
charCodeAt() 返回指定索引處字符的 Unicode 數值。
語法:str.charCodeAt(index)
index 為一個從0至length-1的整數。如果不是一個數值,則默認為 0,如果小于0或者大于字符串長度,則返回 NaN。
Unicode 編碼單元(code points)的范圍從 0 到 1,114,111。開頭的 128 個 Unicode 編碼單元和 ASCII 字符編碼一樣.
charCodeAt() 總是返回一個小于 65,536 的值。因為高位編碼單元需要由一對字符來表示,為了查看其編碼的完成字符,需要查看 charCodeAt(i) 以及 charCodeAt(i+1)
console.log("Hello, World".charCodeAt(8)); // 111 console.log("前端工程師".charCodeAt(2)); // 24037, 可見也可以查看中文Unicode編碼
concat
concat() 方法將一個或多個字符串拼接在一起,組成新的字符串并返回。
語法:str.concat(string2, string3, …)
console.log("早".concat("上","好")); // 早上好 1
但是 concat 的性能表現不佳,強烈推薦使用賦值操作符(+或+=)代替 concat。”+” 操作符大概快了 concat 幾十倍。
indexOf 和 lastIndexOf
indexOf() 方法用于查找子字符串在字符串中首次出現的位置,沒有則返回 -1。該方法嚴格區分大小寫,并且從左往右查找。而 lastIndexOf 則從右往左查找,其它與前者一致。
語法:str.indexOf(searchValue [, fromIndex=0]),str.lastIndexOf(searchValue [, fromIndex=0])
searchValue 表示被查找的字符串,fromIndex 表示開始查找的位置,默認為0,如果小于0,則查找整個字符串,若超過字符串長度,則該方法返回-1,除非被查找的是空字符串,此時返回字符串長度。
console.log("".indexOf("",100)); // 0 console.log("IT改變世界".indexOf("世界")); // 4 console.log("IT改變世界".lastIndexOf("世界")); // 4
localeCompare
localeCompare() 方法用來比較字符串,如果指定字符串在原字符串的前面則返回負數,否則返回正數或0,其中0 表示兩個字符串相同。該方法實現依賴具體的本地實現,不同的語言下可能有不同的返回。
語法:str.localeCompare(str2 [, locales [, options]])
var str="apple"; var str2="orange"; console.log(str.localeCompare(str2)); // -1 console.log(str.localeCompare("123")); // 1
match
match() 方法用于測試字符串是否支持指定正則表達式的規則,即使傳入的是非正則表達式對象,它也會隱式地使用new RegExp(obj)將其轉換為正則表達式對象。
語法:str.match(regexp)
該方法返回包含匹配結果的數組,如果沒有匹配項,則返回 null。
描述
相關 RegExp 方法
var str="World Internet Conference"; console.log(str.match(/[a-d]/i)); // ["d", index: 4, input: "World Internet Conference"] console.log(str.match(/[a-d]/gi)); // ["d", "C", "c"] // RegExp 方法如下 console.log(/[a-d]/gi.test(str)); // true console.log(/[a-d]/gi.exec(str)); // ["d", index: 4, input: "World Internet Conference"]
由上可知,RegExp.test(str) 方法只要匹配到了一個字符也返回true。而RegExp.exec(str) 方法無論正則中有沒有包含 g 標志,RegExp.exec將直接返回第一個匹配結果,且該結果同 str.match(regexp) 方法不包含 g 標志時的返回一致。
replace
語法 str.replace( regexp | substr, newSubStr | function[, flags] )
參數
簡單概括,replace擁有兩個參數,第一個是需要替換的字符串或者正則表達式;第二個是新的字符串或者一個function,這樣參數便有四種組合.
該方法并不改變調用它的字符串本身,而只是返回替換后的字符串.
var b=a.replace("before","after"); console.log(b); // "what is this? after"
如果第一個參數是正則表達式,新的字符串中可以用$符號取正則中匹配的子串(也就是正則中被括號包裹的部分):
var a="what is this? before"; var b=a.replace(/(^\w+).*?(\w+)$/,"$2 $1");//括號分割的部分依次為子串1....n console.log(b); // "before what"
第二個參數其實可為一個function,最終字符串將以function的返回值作為replace的返回值,以下是該function的形參: function(match,p1…,offset,string),可見至少包含三個形參(即arguments.length>=3)
function replacer(match,p1,p2,offset,string){ //此時p1=" is",p2=" this" return p1+" that";//如果返回為空串,則匹配內容替換為空,如果不返回,則匹配內容替換為undefined } var a="what is this? before"; var b=a.replace(/(\s\w+)(\s\w+)/,replacer); console.log(b); // "what is that? before" function replacer(match,offset,string){ //由于字符串中不會有括號進行分組,此時沒有子串 return offset+" that";//偏移為4 } var a="what is this? before"; var b=a.replace(" is this",replacer); console.log(b); // "what4 that? before"
基于 replace 方法的第三個用法, 我們可以實現一個tmpl方法, 輸入一個模板字符串, 輸入一個key-value對象, 即可生成新的字符串.
var template="one {a} two {b} {c}", obj={a:"apple",b:"orange",c:"..."}, _array=[]; function tmpl(template,obj){ var retu=template.replace(/([^{}]*){(.)}/g,function(match,p1,p2,offset,string){ _array.push({'match':match, 'p1':p1, 'p2':p2, 'offset':offset, 'string':string}); return p1+obj[p2]; }); console.table && console.table(_array); !console.table && console.log(_array); console.log(retu); } tmpl(template,obj);
.(小數點):匹配除換行符之外的任何單個字符。例如,/.n/將會匹配 "nay, an apple is on the tree" 中的 'an' 和 'on',但是不會匹配 'nay'。
[^xyz]:一個反向字符集。也就是說, 它匹配任何沒有包含在方括號中的字符。你可以使用破折號(-)來指定一個字符范圍。任何普通字符在這里都是起作用的。例如,[^abc] 和 [^a-c] 是一樣的。他們匹配"brisket"中的‘r’,也匹配“chop”中的‘h’。
search
search() 方法用于測試字符串對象是否包含某個正則匹配,相當于正則表達式的 test 方法,且該方法比 match() 方法更快。如果匹配成功,search() 返回正則表達式在字符串中首次匹配項的索引,否則返回-1。
注意:search方法與indexOf方法作用基本一致,都是查詢到了就返回子串第一次出現的下標,否則返回-1,唯一的區別就在于search默認會將子串轉化為正則表達式形式,而indexOf不做此處理,也不能處理正則
語法:str.search(regexp) var str="abcdefg"; console.log(str.search(/[d-g]/)); // 3, 匹配到子串"defg",而d在原字符串中的索引為3
search() 方法不支持全局匹配(正則中包含g參數),如下:
console.log(str.search(/[d-g]/g)); // 3, 與無g參數時,返回相同
slice
slice() 方法提取字符串的一部分,并返回新的字符串。該方法有些類似 Array.prototype.slice 方法。
語法:str.slice(start, end)
首先 end 參數可選,start可取正值,也可取負值。
var str="It is our choices that show what we truly are, far more than our abilities."; console.log(str.slice(0,-30)); // It is our choices that show what we truly are console.log(str.slice(-30)); // , far more than our abilities.
split
split() 方法把原字符串分割成子字符串組成數組,并返回該數組。
語法:str.split(separator, limit)
兩個參數均是可選的,其中 separator 表示分隔符,它可以是字符串也可以是正則表達式。如果忽略 separator,則返回的數組包含一個由原字符串組成的元素。如果 separator 是一個空串,則 str 將會被分割成一個由原字符串中字符組成的數組。limit 表示從返回的數組中截取前 limit 個元素,從而限定返回的數組長度。
var str="today is a sunny day"; console.log(str.split()); // ["today is a sunny day"] console.log(str.split("")); // ["t", "o", "d", "a", "y", " ", "i", "s", " ", "a", " ", "s", "u", "n", "n", "y", " ", "d", "a", "y"] console.log(str.split(" ")); // ["today", "is", "a", "sunny", "day"]
使用limit限定返回的數組大小,如下:
console.log(str.split(" ", 1)); // ["today"] console.log(str.split(/\s*is\s*/)); // ["today", "a sunny day"] // 若正則分隔符里包含捕獲括號,則括號匹配的結果將會包含在返回的數組中。 console.log(str.split(/(\s*is\s*)/)); // ["today", " is ", "a sunny day"]
substr
substr() 方法返回字符串指定位置開始的指定數量的字符。
語法:str.substr(start[, length])
start 表示開始截取字符的位置,可取正值或負值。取正值時表示start位置的索引,取負值時表示 length+start位置的索引。
length 表示截取的字符長度。
var str="Yesterday is history. Tomorrow is mystery. But today is a gift."; console.log(str.substr(47)); // today is a gift. console.log(str.substr(-16)); // today is a gift.
substring
substring() 方法返回字符串兩個索引之間的子串。
語法:str.substring(indexA[, indexB])
indexA、indexB 表示字符串索引,其中 indexB 可選,如果省略,則表示返回從 indexA 到字符串末尾的子串。
描述
substring 要截取的是從 indexA 到 indexB(不包含)之間的字符,符合以下規律:
var str="Get outside every day. Miracles are waiting everywhere."; console.log(str.substring(1,1)); // "" console.log(str.substring(0)); // Get outside every day. Miracles are waiting everywhere. console.log(str.substring(-1)); // Get outside every day. Miracles are waiting everywhere. console.log(str.substring(0,100)); // Get outside every day. Miracles are waiting everywhere. console.log(str.substring(22,NaN)); // Get outside every day.
toLocaleLowerCase & toLocaleUpperCase
toLocaleLowerCase() 方法返回調用該方法的字符串被轉換成小寫的值,轉換規則根據本地化的大小寫映射。而toLocaleUpperCase() 方法則是轉換成大寫的值。
語法:str.toLocaleLowerCase(), str.toLocaleUpperCase()
console.log('ABCDEFG'.toLocaleLowerCase()); // abcdefg console.log('abcdefg'.toLocaleUpperCase()); // ABCDEFG
toLowerCase & toUpperCase
這兩個方法分別表示將字符串轉換為相應的小寫,大寫形式,并返回
console.log('ABCDEFG'.toLowerCase()); // abcdefg console.log('abcdefg'.toUpperCase()); // ABCDEFG
toString & valueOf
這兩個方法都是返回字符串本身。
語法:str.toString(), str.valueOf()
var str="abc"; console.log(str.toString()); // abc console.log(str.toString()==str.valueOf()); // true
對于對象而言,toString和valueOf也是非常的相似,它們之間有著細微的差別,請嘗試運行以下一段代碼:
var x={ toString: function () { return "test"; }, valueOf: function () { return 123; } }; console.log(x); // test console.log("x=" + x); // "x=123" console.log(x + "=x"); // "123=x" console.log(x + "1"); // 1231 console.log(x + 1); // 124 console.log(["x=", x].join("")); // "x=test"
當 “+” 操作符一邊為數字時,對象x趨向于轉換為數字,表達式會優先調用 valueOf 方法,如果調用數組的 join 方法,對象x趨向于轉換為字符串,表達式會優先調用 toString 方法。
trim
trim() 方法清除字符串首尾的空白并返回。
語法:str.trim()
console.log(" a b c ".trim()); // "a b c"
trim() 方法是 ECMAScript 5.1 標準加入的,它并不支持IE9以下的低版本IE瀏覽器
if(!String.prototype.trim) { String.prototype.trim=function () { return this.replace(/^\s+|\s+$/g,''); }; }
codePointAt(ES6)
codePointAt() 方法基于ECMAScript 2015(ES6)規范,返回使用UTF-16編碼的給定位置的值的非負整數。
語法:str.codePointAt(position)
console.log("a".codePointAt(0)); // 97 console.log("\u4f60\u597d".codePointAt(0)); // 20320
includes(ES6)
includes() 方法基于ECMAScript 2015(ES6)規范,它用來判斷一個字符串是否屬于另一個字符。如果是,則返回true,否則返回false。
語法:str.includes(subString [, position])
subString 表示要搜索的字符串,position 表示從當前字符串的哪個位置開始搜索字符串,默認值為0。
var str="Practice makes perfect."; console.log(str.includes("perfect")); // true console.log(str.includes("perfect",100)); // false
實際上,Firefox 18~39中該方法的名稱為contains,由于bug 1102219的存在,它被重命名為includes() 。目前只有Chrome v41+和Firefox v40+版本瀏覽器實現了它,如需在其它版本瀏覽器中使用該方法,請參考 Polyfill。
endsWith(ES6)
endsWith() 方法基于ECMAScript 2015(ES6)規范,它基本與 contains() 功能相同,不同的是,它用來判斷一個字符串是否是原字符串的結尾。若是則返回true,否則返回false。
語法:str.endsWith(substring [, position])
與contains 方法不同,position 參數的默認值為字符串長度。
var str="Learn and live."; console.log(str.endsWith("live.")); // true console.log(str.endsWith("Learn",5)); // true
startsWith(ES6)
startsWith() 方法基于ECMAScript 2015(ES6)規范,它用來判斷當前字符串是否是以給定字符串開始的,若是則返回true,否則返回false。
語法:str.startsWith(subString [, position])
var str="Where there is a will, there is a way."; console.log(str.startsWith("Where")); // true console.log(str.startsWith("there",6)); // true
normalize(ES6)
normalize() 方法基于ECMAScript 2015(ES6)規范,它會按照指定的 Unicode 正規形式將原字符串正規化。
語法:str.normalize([form])
form 參數可省略,目前有四種 Unicode 正規形式,即 “NFC”、”NFD”、”NFKC” 以及 “NFKD”,form的默認值為 “NFC”。如果form 傳入了非法的參數值,則會拋出 RangeError 錯誤。
var str="\u4f60\u597d"; console.log(str.normalize()); // 你好 console.log(str.normalize("NFC")); // 你好 console.log(str.normalize("NFD")); // 你好 console.log(str.normalize("NFKC")); // 你好 console.log(str.normalize("NFKD")); // 你好 function toUnicode(theString) { var unicodeString=''; for (var i=0; i < theString.length; i++) { var theUnicode=theString.charCodeAt(i).toString(16).toUpperCase(); while (theUnicode.length < 4) { theUnicode='0' + theUnicode; } theUnicode='\\u' + theUnicode; unicodeString +=theUnicode; } return unicodeString; } toUnicode('你好'); // "\u4f60\u597d"
repeat(ES6)
repeat() 方法基于ECMAScript 2015(ES6)規范,它返回重復原字符串多次的新字符串。
語法:str.repeat(count)
count 參數只能取大于等于0 的數字。若該數字不為整數,將自動轉換為整數形式,若為負數或者其他值將報錯。
var str="A still tongue makes a wise head."; console.log(str.repeat(0)); // "" console.log(str.repeat(1)); // A still tongue makes a wise head. console.log(str.repeat(1.5)); // A still tongue makes a wise head. console.log(str.repeat(-1)); // RangeError:Invalid count value
常用的方法有 anchor,link 其它方法如 big、blink、bold、fixed、fontcolor、fontsize、italics、small、strike、sub、sup均已廢除。
接下來我們將介紹 anchor 和 link 兩個方法,其他廢除方法不作介紹。
anchor
anchor() 方法創建一個錨標簽。
語法:str.anchor(name)
name 指定被創建的a標簽的name屬性,使用該方法創建的錨點,將會成為 document.anchors 數組的元素。
var str="this is a anchor tag"; document.body.innerHTML=document.body.innerHTML + str.anchor("anchor1"); // body末尾將會追加這些內容 <a name="anchor1">this is a anchor tag</a>
link
link() 方法同樣創建一個a標簽。
語法:str.link(url)
url 指定被創建的a標簽的href屬性,如果url中包含特殊字符,將自動進行編碼。例如 " 會被轉義為 &\quot。 使用該方法創建的a標簽,將會成為 document.links 數組中的元素。
var str="百度"; document.write(str.link("https://www.baidu.com")); // <a >百度</a>
小結
部分字符串方法之間存在很大的相似性,要注意區分他們的功能和使用場景。如:
substr 和 substring,都是兩個參數,作用基本相同,兩者第一個參數含義相同,但用法不同,前者可為負數,后者值為負數或者非整數時將隱式轉換為0。前者第二個參數表示截取字符串的長度,后者第二個參數表示截取字符串的下標;同時substring第一個參數大于第二個參數時,執行結果同位置調換后的結果。 search方法與indexOf方法作用基本一致,都是查詢到了就返回子串第一次出現的下標,否則返回-1,唯一的區別就在于search默認會將子串轉化為正則表達式形式,而indexOf不做此處理,也不能處理正則。 另外,還記得嗎?concat方法由于效率問題,不推薦使用。
通常,字符串中,常用的方法就charAt、indexOf、lastIndexOf、match、replace、search、slice、split、substr、substring、toLowerCase、toUpperCase、trim、valueof 等這些。熟悉它們的語法規則就能熟練地駕馭字符串
參考文章:
https://segmentfault.com/a/1190000010753942
https://segmentfault.com/a/1190000012688190
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String
ypeScript 和 JavaScript 是目前項目開發中較為流行的兩種腳本語言,我們已經熟知 TypeScript 是 JavaScript 的一個超集,但是 TypeScript 與 JavaScript 之間又有什么樣的區別呢?在選擇開發語言時,又該如何抉擇呢?
本文將會深入對比這兩種語言,討論兩種語言之間的關聯和差異,并概述兩種語言各自的優勢。
JavaScript
JavaScript 是一種輕量級的解釋性腳本語言,可嵌入到 HTML 頁面中,在瀏覽器端執行,能夠實現瀏覽器端豐富的交互功能,為用戶帶來流暢多樣的用戶體驗。
JavaScript 是基于對象和事件驅動的,無需特定的語言環境,只需在支持的瀏覽器上就能運行。
JavaScript 語言具有以下特點:
JavaScript 是一種腳本編寫語言,無需編譯,只要嵌入 HTML 代碼中,就能由瀏覽器逐行加載解釋執行。
JavaScript 是一種基于對象的語言,可以創建對象同時使用現有對象。但是 Javascript 并不支持其它面向對象語言所具有的繼承和重載功能。
JavaScript 的語法簡單,使用的變量為弱類型。
JavaScript 語言較為安全,僅在瀏覽器端執行,不會訪問本地硬盤數據。
JavaScript 語言具有動態性。JavaScript 是事件驅動的,只根據用戶的操作做出相應的反應處理。
JavaScript 只依賴于瀏覽器,與操作系統的因素無關。因此 JavaScript 是一種跨平臺的語言。
JavaScript 兼容性較好,能夠與其他技術(如 XML,REST API 等)一起使用。
TypeScript
TypeScript 是 Microsoft 開發和維護的一種面向對象的編程語言。它是 JavaScript 的超集,包含了 JavaScript 的所有元素,可以載入 JavaScript 代碼運行,并擴展了 JavaScript 的語法。
TypeScript 具有以下特點:
TypeScript 是 Microsoft 推出的開源語言,使用 Apache 授權協議
TypeScript 增加了靜態類型、類、模塊、接口和類型注解
TypeScript 可用于開發大型的應用
TypeScript 易學易于理解
TypeScript 可以使用 JavaScript 中的所有代碼和編碼概念,TypeScript 是為了使 JavaScript 的開發變得更加容易而創建的。例如,TypeScript 使用類型和接口等概念來描述正在使用的數據,這使開發人員能夠快速檢測錯誤并調試應用程序
TypeScript 從核心語言方面和類概念的模塑方面對 JavaScript 對象模型進行擴展。
JavaScript 代碼可以在無需任何修改的情況下與 TypeScript 一同工作,同時可以使用編譯器將 TypeScript 代碼轉換為 JavaScript。
TypeScript 通過類型注解提供編譯時的靜態類型檢查。
TypeScript 中的數據要求帶有明確的類型,JavaScript不要求。
TypeScript 為函數提供了缺省參數值。
TypeScript 引入了 JavaScript 中沒有的“類”概念。
TypeScript 中引入了模塊的概念,可以把聲明、數據、函數和類封裝在模塊中。
下面列舉 TypeScript 相比于 JavaScript 的顯著優勢:
1. 靜態輸入
靜態類型化是一種功能,可以在開發人員編寫腳本時檢測錯誤。查找并修復錯誤是當今開發團隊的迫切需求。有了這項功能,就會允許開發人員編寫更健壯的代碼并對其進行維護,以便使得代碼質量更好、更清晰。
2. 大型的開發項目
有時為了改進開發項目,需要對代碼庫進行小的增量更改。這些小小的變化可能會產生嚴重的、意想不到的后果,因此有必要撤銷這些變化。使用TypeScript工具來進行重構更變的容易、快捷。
3. 更好的協作
當發開大型項目時,會有許多開發人員,此時亂碼和錯誤的機也會增加。類型安全是一種在編碼期間檢測錯誤的功能,而不是在編譯項目時檢測錯誤。這為開發團隊創建了一個更高效的編碼和調試過程。
4. 更強的生產力
干凈的 ECMAScript 6 代碼,自動完成和動態輸入等因素有助于提高開發人員的工作效率。這些功能也有助于編譯器創建優化的代碼。
相比于 TypeScript,JavaScript 也有一些明顯優勢。
1. 人氣
JavaScript 的開發者社區仍然是巨大而活躍的,在社區中可以很方便地找到大量成熟的開發項目和可用資源。
2. 學習曲線
由于 JavaScript 語言發展的較早,也較為成熟,所以仍有一大批開發人員堅持使用他們熟悉的腳本語言 JavaScript,而不是學習 TypeScript。
3. 本地瀏覽器支持
TypeScript 代碼需要被編譯(輸出 JavaScript 代碼),這是 TypeScript 代碼執行時的一個額外的步驟。
4. 不需要注釋
為了充分利用 TypeScript 特性,開發人員需要不斷注釋他們的代碼,這可能會使項目效率降低。
5. 靈活性
有些開發人員更喜歡 JavaScript 的靈活性。
TypeScript 正在成為開發大型編碼項目的有力工具。因為其面向對象編程語言的結構保持了代碼的清潔、一致和簡單的調試。因此在應對大型開發項目時,使用 TypeScript 更加合適。如果有一個相對較小的編碼項目,似乎沒有必要使用 TypeScript,只需使用靈活的 JavaScript 即可。
*請認真填寫需求信息,我們會在24小時內與您取得聯系。