JS學習筆記整理三 引用類型

引用類型

Object類型

經過對象字面量建立對象時,實際上不會調用Object構造函數。所以,經過這種方式更快速更直觀。javascript

對象字面量比較適合用於傳參,利用typeof來檢查對象傳入的每個屬性是否存在。html

對象的屬性能夠用點表示法和方括號表示法。java

方括號表示法能夠利用變量訪問屬性。同時屬性可名能夠包括非字母和非數字,這種狀況只能用方括號形式訪問。在定義時這種狀況的屬性名要用引號。node

Array類型

不要這麼聲明數組:git

var a=[,,,,];或者var a=[1,2,];會出buges6

數組的length屬性不是隻讀的,咱們能夠設置長度,length加長時,未初始化的值都命名爲undefined,變短時末尾的部分被移除。github

檢測數組。

typeof

這個地方仍是說明一下,typeof能檢測如下幾種類型:web

undefined,string,number,boolean,object,function es6新增了symbol. 宿主對象正則表達式

可是對於數組,typeof操做符就沒辦法。array類型和null類型最後都會返回object。算法

typeof的一些特殊行爲

typeof 1/0; //NaN(這個NaN不是字符串類型,是數值類型)
typeof typeof 1/0; //NaN(這個NaN不是字符串類型,是數值類型)
typeof(1/0); //"number"
typeof typeof(1/0); //"string"
typeof (typeof 1/0); //"number"

複製代碼

instanceof

對於instanceof操做符。原理是查找被檢測構造函數的prototype是否在如今對象的原型鏈上。若是是返回true,不然false。所以,instanceof能夠檢測判斷自定義對象。可是在多個全局做用域的狀況中,instanceof沒法檢測另外一個全局做用域的對象類型。並且,瀏覽器開始支持原生JSON。如今很難用instanceof來判斷是原生仍是自定義了。

Object.prototype.toString.call(value)

使用Object.prototype.toString.call(value);能夠返回[object nativeConstructorName]格式字符串。經過這種方式,咱們能檢測出原生構造函數名。好比Array和正則等。可是自定義的不行,只會返回[object object]。

之因此使用Object.prototype.toString是由於其餘類型繼承Object後把方法都重寫了。

(紅皮書p8八、p596)

Array.isArray(value)

es5新增了Array.isArray()方法,用來最終肯定某個值究竟是不是數組,而無論它是在那個全局執行環境中建立的。

轉換方法。

數組的toString實際上是調用的每一項元素的toString(),toLocaleString調用的是每一項元素的toLocaleString()。

棧方法

後進先出LIFO

pushpop。push能夠一次性傳入多個數組元素,最後返回添加後的數組長度。pop則推出最後一個數組元素並返回值。

隊列方法

先進先出FIFO

使用pushshift

從新排序方法

reverse()反轉數組 sort()排序

var a=[13,24,1,64,27];
console.log(a.sort((v1,v2)=>v1-v2));
複製代碼

數組的操做方法

concatslice 原數組不變,返回新數組

splice則能夠添加替換刪除數組內元素,算是最強大的數組方法。

var a2=a1.spalice(起始位置,刪除項數,插入項1,插入項2...);
複製代碼

位置方法

indexOflastIndexOf

迭代方法

everyfilterforEachmapsome

它們都是對數組運行一個給定的函數

every是當函數對每一項都返回true,則返回true。好比對dom數組進行遍歷,當知足某一條件返回false。終止接下來的遍歷。

some是當函數對其中一項返回true,則返回true

filter是返回符合條件爲true的元素組成的數組

map是返回運算後元素組成的數組

forEach沒有返回值。

array.forEach(function(currentValue, index, arr), thisValue);
複製代碼

須要注意的是這些遍歷方法的第二個參數。若是有第二個參數,則將其做爲this值指定的對象傳入到回調函數內。以前講過匿名函數this是指向全局的,這種至關於改變了做用域鏈。

歸併方法

reducereduceRight這兩個函數很是好用,

reduce進階:轉載:https://segmentfault.com/a/1190000010731933

紅皮書p98,犀牛書158

reduce有兩個參數,第一個參數是要執行並歸計算的函數,此函數包含四個參數:初始值、當前元素、索引(可選)、數組(可選)。第二個可選是執行操做的初始值。若是不指定第二個參數,則第一次並歸計算將使用數組第一個和第二個元素做爲函數的兩個參數傳入。

補充一個unshift,紅皮書裏沒找到。在數組的頭部插入元素。但記住,一次性插入參數和一個一個插入,順序是不同的。

Date類型

玩遊戲的時候會常常遇到通知發售日或維護時間。有時以UTC有時用GMT,還有CST、EST、JST、HKT

說到時區,忍不住百度了下中學地理2333。地球公轉和自轉有23度左右夾角。由於角動量守恆,地軸方向基本是不變的。地球自轉和公轉方向都是自西向東。因此太陽總從東邊出來。

位於東邊的地區老是先迎接太陽。

GMT叫格林威治時間, UTC叫協調標準時

咱們使用東八區的北京時間。所以,咱們的本地時間應該是標準時UTC加8小時。

北京時間=UTC+8=GMT+8。

使用new Date()建立日期對象

若是不給參數,直接得到當前時間。若是須要參數,則需傳入表示該日期的毫秒數。若是傳入字符串,則會先調用Date.parse()解析成毫秒數。也能夠模仿Date.UTC格式參數,可是會把參數當成本地時間解析。沒法解析返回Invalid Date。

Now=new Date();
複製代碼

直接輸出Now和Now.toString()內容是不同的。直接輸出是標準時間,toString輸出本地時間。Date.parse接受的字符串若是不特地註明時區,是按照本地時間解析的。而Date.UTC則是按照標準時間解析

Mon Mar 18 2019 10:26:18 GMT+0800(GMT+08:00)

Gmt+8是北京時間。必定要注意,上面字符串寫法中GMT+0800後面兩個零表明分鐘數。所以,+0860等同於+0900。

一個倒計時練習。

(function(){
    var targetTime=Date.parse("2019-7-19 11:10:00 gmt+0800");//選一個還沒到的日期
    var sub =targetTime- Date.now();
    if(sub>0){
        var min,sec,hour,day,st,intervalId;
        intervalId=setInterval(countDown,1000);
    }
    function countDown(){
        sub = targetTime - Date.now();
        if(sub>0){
            st=sub/1000;
            day=~~(st/86400);
            hour=~~((st-day*86400)/3600);
            min=~~(st/60)%60;
            sec=~~st%60;
            console.log(day+"天"+hour+"時"+min+"分"+sec+"秒");
        }else{
            clearInterval(intervalId);
   }
    }
})();
複製代碼

不要寫超出時間範圍的值,不一樣瀏覽器的解析有差別。

Date.now()表示調用時的時間毫秒數。若是在不支持的舊版本瀏覽器,可使用+new Date()來獲取時間戳。由於使用加號會調用valueOf。用getTime不夠簡潔。

RegExp類型

Regular expression 正則表達式實際上是一塊學起來特別有意思的部分。

表達式格式:/ pattern / flags

pattern:模式,flags:標誌。

正則表達式的元字符:(){}[].?=!:/\|^$*+

若是須要匹配這些字符,必須使用反斜\進行轉義

能夠用漢字「八」來輔助記憶 / 正斜 \ 反斜

元字符和部分字母的轉義組成有特殊含義的符號,固然,部分字符只在特定的上下文中才有意義。敲一遍常見的\n,\t,\v,\r,\f

字符類

[...] 方括號內的任意字符

[^...] 不在方括號內的任意字符

. 除換行符和其餘Unicode行終止符之外的任意字符(排除\n和\r)

\w 任何ASCII字符組成的單詞,等價於[a-zA-Z0-9]

\W 任何非ASCII字符組成的單詞,等價於[^a-zA-Z0-9]

\s包含Unicode任意空白符。經測試,\s涵蓋\n,\t,\v,\r,\f這幾項。

\S 任何非Unicode空白符,注意\w和\S不一樣

\d 任何ASCII數字,等價於[0-9]

\D 除了ASCII數字以外的任何字符,等價於[^0-9]

\b 能夠理解爲單詞的邊界 注意區別[\b]退格符

重複

?={0,1} *={0,} +={1,}

重複分爲貪婪的重複和非貪婪的重複。貪婪的重複會盡量多的匹配直到最大的次數。而非貪婪的匹配,需在匹配內容後加?,只要配上了就返回,然後面的重複能夠繼續從新匹配。須要注意的是非貪婪匹配可能返回與指望值不一致的結果。好比對於字符串"aaaab"和正則表達式/a+?b/,返回的不是"ab",而是"aaaab"。由於模式匹配總會尋找字符串中第一個匹配的位置。

常見的兩種類型模式匹配的語句:

  1. str.match(pattern);

    全局修飾符g時,會返回一個匹配成功後的字符串數組。不然返回首個匹配元素和索引等信息。

  2. pattern.exec(str)

    若是匹配成功,始終返回一個數組

選擇、分組和引用

|能夠用於分割供選擇的字符。不一樣的項從左到右匹配,若是左側的匹配了,則會跳過右側的,即使有更優的選擇。

()圓括號能夠對括號內的內容當作一個獨立的單元處理。另外的做用就是定義子模式,並供後部引用。根據左括號的排序數字如:\2 引用以前匹配到的同樣的字符內容,而不是引用同樣的模式。 (?: )能夠做爲不生成引用的分組。

var s = 'aaa_aa_a';
console.log(s.match(/(a+)_\1/));//[ 'aa_aa' ]
複製代碼

AscII 一個字節。能夠表示256個字符。

Unicode是兩字節,共能表示65536個字符。Ascii其實算是unicode的子集。首字節都是0,則末字節恰好表示ascii的256個編碼。

Utf-8是針對Unicode的可變長度字符編碼,俗稱萬國碼。一般狀況是三個字節。也有六子字節的狀況,不多見。

1110xxxx

10xxxxxx

10xxxxxx

關於漢字的匹配:轉載:https://www.cnblogs.com/ChengDong/articles/3771880.html 雖然繁簡體的漢字加一塊兒六七萬個。可是經常使用的就六七千個。

疑問:若是gb2132的頁面,可否經過這種方式判斷成功呢?大體查了下,

網上有些人用的是排除法。

指定匹配位置

犀牛書把先行斷言lookahead assert(零寬斷言)和其餘的錨字符一塊兒講了。由於他們都表明一個零寬的位置。

網上一些教程把斷言和()圓括號分組一塊兒講了。由於他們都是表現爲分組的形式。

錨字符整理:

^ 匹配字符串的開頭,在多行檢索中匹配一行的開頭。

$ 匹配字符串的結尾,在多行檢索中匹配一行的結尾

\b 匹配一個單詞的邊界,就是\w和\W之間的位置,或\w與字符串開頭或結尾之間的位置。

\B 匹配非單詞邊界的位置

(?=p) 零寬正向先行斷言,要求接下來的字符都和p匹配,但不能包括匹配p的那些字符

(?!p) 零寬負向先行斷言,要求接下來的字符不與p匹配

另外,犀牛書裏目前只看到兩種,叫先行斷言。其實還有後行斷言。

結合分組寫到一塊兒:

() 捕獲型分組能夠被後面捕獲並引用

(?:) 非捕獲型分組 不能被捕獲

(?= pattern) 正向先行斷言

(?! pattern) 負向先行斷言

(?<= pattern) 正向後行斷言 後行斷言要放在判斷字符的前面

(?<! pattern) 負向先行斷言

犀牛書p253註釋說明js不支持後行斷言。可是我測試的時候並無報錯,並且返回正確結果了。我用的ide是webstorm,按照nodejs運行的,nodejs就是基於v8的。查了一下,新標準裏有後行斷言擴展,版本新一點的v8引擎已經支持後行斷言。

後向引用(也叫反向引用?),若是引用放到圓括號前面,會發生什麼?測試了一下,有的時候能返回想要的內容。但又想了一下,這樣沒什麼意義。在pattern裏引用寫爲\number,程序裏引用寫爲$number

後向引用能夠本身定義組名,這樣能夠加強表達式的可讀性。

(?<NAME>pattern)
複製代碼

正則表達式內引用時使用: \k<NAME>,程序裏引用寫爲$<NAME>

紅皮書p109說ecmascript不支持命名的捕獲組。可是上面的測試經過了,難道又是新版es支持的擴展? 經查,V8 目前已經徹底實現了命名捕獲分組的提案。

轉載:https://tc39.github.io/proposal-regexp-named-groups/

一旦支持了命名的捕獲組,是否可以支持平衡組,遞歸匹配?反覆看了看,沒有找到依據,javascript相關資料太少,太耽誤時間,放棄了。

經測,條件判斷表達式不可用。(?(expression)yes|no)紅皮書109

犀牛書p253註釋說明js不支持註釋。。。

(?#註釋用格式,對錶達式不會有影響) //報錯
複製代碼

修飾符flag

g 全局,檢索全部匹配。

m多行,除了匹配字符串的開始和結尾,還能夠用^匹配一行的開頭,$匹配到一行的結尾。

i 忽略大小寫

es6新增了修飾符uy

u 含義爲「Unicode 模式」,用來正確處理大於\uFFFF的 Unicode 字符。也就是說,會正確處理四個字節的 UTF-16 編碼。

y 叫作「粘連」(sticky)修飾符。做用與g修飾符相似,也是全局匹配,後一次匹配都從上一次匹配成功的下一個位置開始。不一樣之處在於,g修飾符只要剩餘位置中存在匹配就可,而y修飾符確保匹配必須從剩餘的第一個位置開始,這也就是「粘連」的涵義。

用於模式匹配的String方法

match 返回匹配的數組,非全局匹配返回的數組包含子表達式和分組信息等 search 返回匹配到內容的索引,返回第一個匹配的起始位置,會忽略修飾符g replace 可使用引用,注意這個方法不會改變str自己。因此,須要賦值表達式把原值銷燬替換爲新值。

var s = 'aaa_aa_a';
console.log(s.replace(/(a+)_\1/g,'"$1"'));
複製代碼

split

RegExp對象

RegExp屬性

regexp實例的經常使用屬性:

sourcelastIndexglobalmultilineignoreCaseflags

RegExp方法

re.exec(str)方法和str.match(pattern)返回的結果很類似。區別在於無論是否是全局,老是返回一個匹配結果構成的數組。當有全局修飾符g的狀況下,調用完方法該對象會把本身的lastIndex屬性置於匹配字符後。下次調用從lastIndex開始查找匹配。

//犀牛書p265示例
var pattern=/Java/g;
var text="JavaScript is more fun than Java!";
var result;
while((result=pattern.exec(text))!=null){
    console.log("match'"+result[0]+"'at position"+result.index+",next search begins at"+pattern.lastIndex);
    console.log(result);
}
//match'Java'at position0,next search begins at4
//[ 'Java',index: 0,input: 'JavaScript is more fun than Java!',groups: undefined ]

//match'Java'at position28,next search begins at32
//[ 'Java',index: 28,input: 'JavaScript is more fun than Java!',groups: undefined ]
複製代碼

re.test(str)返回值和exec()方法不同,其餘的行爲是和exec同樣的。

一些狀況須要手動設置lastIndex爲0,以方便未來的檢索。

對於正則表達式字面量,新的v8等等都是返回新實例對象。而不像過去共享同一個對象。

re.toString()和re.toLocaleString()都返回正則字面量,而re.valueOf()返回re對象自己。。。

Regexp構造函數包含一些屬性,適用於做用域中全部的正則表達式。按照最後一次正則表達式操做爲準。

RegExp.inputRegExp.lastMatchRegExp.lastParenRegExp.multilineRegExp.leftContextRegExp.rightContext

對於匹配的子表達式,使用$1$9儲存。在使用exec()或者test()方法時,上面這些屬性會被自動填充。

轉載一個正則表達式30分鐘入門教程:deerchao.net/tutorials/r…

對理解正則表達式頗有幫助,可是其中一部分在javascript中尚未支持,有些語法也不盡相同。

Function類型

函數聲明、函數表達式、構造函數

定義函數的三種方法,前兩種都比較常見:

  1. 函數聲明語法
    function sum(num1,num2){
      return num1+num2
    }
    複製代碼
  2. 函數表達式語法
    var sum=function(num1,num2){
      return num1+num2
    }
    複製代碼
  3. 構造函數
    var sum=new Function(「num1」,」num2」,」return num1+num2」);
    複製代碼
    最後一種形式,存在幾個個問題:1.會致使二次解析代碼。由於傳入的參數是字符串。2.每次調用構造函數都會返回新的函數。3.這種形式建立的函數不會使用詞法做用域。會在頂級被編譯。
    var y = "global";
    function constructFunction() {
        var y = "local";
        return new Function("return y");
    }
    console.log(constructFunction()());
    複製代碼
function a(){
}
console.log(Object.getOwnPropertyNames(a));
複製代碼

Object.getOwnPropertyNames 列出自身可枚舉和不可枚舉的屬性。 prototype指向構造函數的原型對象。在es5內是沒法枚舉的對象。因此for-in沒法發現。

var haha=function a(){
}
console.log(haha.name);//a;
console.log(a);//未定義,由於是當成表達式,會忽略函數聲明的方法名
複製代碼

函數的內部屬性

函數的內部有兩個特殊的對象,arguments和this

arguments是個類數組,有兩個經常使用屬性 :

  • callee指向擁有此對象的函數。
  • length,arguments的長度

call和apply區別就是傳遞參數的不一樣。

this機制文章:轉載:https://www.cnblogs.com/xiaohuochai/p/5735901.html

var o = {
    m: function(){
        return this;
    }
}
var obj=new o.m();
console.log(obj,obj === o);//{} false
console.log(obj.constructor === o.m);
複製代碼

這裏雖然o.m看起來是做爲o的方法調用。但實際上return this返回的卻不是o,這裏的this實際是做爲構造對象m的新對象返回的。

函數的四種調用方式:獨立調用、方法調用、間接調用和構造函數調用。

轉載的文章最後一句話很好:說到底,javascript如此複雜的緣由是由於函數過於強大。由於,函數是對象,因此原型鏈比較複雜。由於函數能夠做爲值被傳遞,因此執行環境棧比較複雜。一樣地,由於函數具備多種調用方式,因此this的綁定規則也比較複雜。

關於setTimeout函數裏this指向修正:

轉載:http://www.cnblogs.com/zsqos/p/6188835.html

  1. 存爲變量,用閉包訪問外層變量。
  2. bind
  3. 箭頭函數=>

數組的遍歷方法 every some filter map forEach均可以經過第二個參數綁定this值。

另外再po一個寫了好多的文章 轉載:https://www.cnblogs.com/venoral/p/5280805.html

基本包裝對象

以前學過基本類型主要有五種:null,undefined,string,number,boolean。

爲了便於操做基本類型值,es提供了三個引用類型:Boolean,Number,String

包裝對象在調用對應基本類型值的時候被建立,調用結束後就被銷燬。因此在運行時不能動態的爲包裝對象添加方法和屬性。

儘可能不要顯示調用特殊類型建立實例。這樣typeof會顯示爲object。

Object構造函數會像工廠方法同樣,返回基本類型實例。

Boolean類型

重寫了valueOf方法,返回基本類型值。toString返回字符串。

可是存在一個問題。放在布爾表達式中,顯示建立的new Boolean(false)對象,會被看成爲真。因此,若是要這麼用,加上valueOf。其實這個對象用處不大。建議永遠別用這個對象。。。

對於基本類型值,instanceof Boolean和instanceof Object都是false。

Number類型

number.toFixed(2) 格式化爲字符串,顯示小數點後兩位:"2.00"

number.toPercision 把數字格式化爲指定的長度,其可能返回固定大小格式也可能返回指數格式。

number.toExponential(1) 指數表示方法

String類型

無論是ascii仍是unicode字符,都按字符數去計算length

字符方法

charAt

charCodeAt輸出字符串編碼

字符串操做方法

注意這幾個方法都不會修改原始值,而是返回新值 concat 可接受任意多個參數進行拼接

slice

substr

substring

字符串位置方法

indexOflastIndexOf搜索字符串,返回子字符串位置,若是沒有返回-1。查找方向不一樣,但位置都是從開頭計數。

trim方法

trim建立不帶任何空格的字符串副本並返回

大小寫轉換

toUpperCase toLocaleUpperCase

toLowerCase toLocaleLowerCase

模式匹配方法

match search split replace

function htmlEscape(text){
    return text.replace(/[<>"&]/g,function(match,pos,orginText){
        switch(match){
            case "<":
                return "&lt;";
            case ">":
                return "&gt;";
            case "\"":
                return "&quot;";
            case "&":
                return "$amp;";
        }
     });
}
console.log(htmlEscape("<p class=\"greeting\">Hello World!</p>"));
複製代碼

存在一個問題,split若是包含捕獲組,會被合併到結果數組內,這是個比較有意思的特性。ie8以前會忽略捕獲組。

var str="ababaabab";
var pattern=/(a){2}/;
console.log(str.split(pattern));//[ 'abab', 'a', 'bab' ]
複製代碼

若是使用時出了這種情況,應該明白是怎麼回事

fromCharCode

function tohanzi(data) {
    if(data == '') return '請輸入十六進制unicode';
    data = data.split("\\u");
    var str ='';
    for(var i=0;i<data.length;i++)
    {
        str+=String.fromCharCode(parseInt(data[i],16).toString());
    }
    return str;
}
function tounicode(data) {
    if(data == '') return '請輸入漢字';
    var str ='';
    for(var i=0;i<data.length;i++)
    {
        str+="\\u"+parseInt(data[i].charCodeAt(0),10).toString(16);
    }
    return str;}
console.log(tohanzi(tounicode("鐵蛋abc\\n\\")));//鐵蛋abc\n\
var num=62;
console.log("abc"[1].charCodeAt().toString(16));//62
複製代碼

單體內置對象

global對象

URI UniformResource Identifier

encodeURI不會對URI的特殊字符進行編碼。用於跳轉

encodeURIComponent對發現的任何非標準字符進行編碼。用於傳參

decodeURI

decodeURIComponent

eval方法

功能很強大,可是儘可能別用。。。

在eval中定義的函數和變量不會提高,由於到語句執行的時候纔會建立。

Math對象

隨機數算法

function selectFrom(lowValue,upperValue){
    var range=upperValue-lowValue+1;
    return Math.floor(Math.random()*range)+lowValue;
}
複製代碼
相關文章
相關標籤/搜索