js基礎(chǔ)(4)

15衍慎、正則

正則就是一個(gè)規(guī)則,用來(lái)處理字符串的規(guī)則
1命迈、正則匹配
編寫(xiě)一個(gè)規(guī)則仇让,驗(yàn)證某個(gè)字符串是否符合這個(gè)規(guī)則,正則匹配使用的是test方法

2躺翻、正則捕獲
編寫(xiě)一個(gè)規(guī)則丧叽,在一個(gè)字符串中把符合規(guī)則的內(nèi)容都獲取到;正則的exec公你、字符串的split踊淳、replace、match等方法都支持正則

正則的創(chuàng)建方式以及區(qū)別

1.字面量方式:var reg=/\d/;
2.實(shí)例創(chuàng)建方式 var reg=new RegExp('a','b');支持兩個(gè)參數(shù)陕靠,第一個(gè)為元字符迂尝,第二個(gè)是修飾符
<font color=red>兩種創(chuàng)建方式的區(qū)別:<font>
1,字面量方式中出現(xiàn)一切字符都會(huì)按找元字符來(lái)解析剪芥,所以不能進(jìn)行變量值的拼接垄开,而實(shí)例創(chuàng)建的方式是可以的。
2税肪,字面量方式中直接寫(xiě)\d就可以溉躲,而在實(shí)例創(chuàng)建方式中需要把它轉(zhuǎn)義;只需要在\d之前再加一個(gè)\即可。即\\d

正則的元字符和修飾符

任何一個(gè)正則都是由元字符修飾符組成的

修飾符

ignoreCase(i):忽略大小寫(xiě);
global(g):全局匹配;找到所有的匹配而不是只找到第一個(gè)匹配
multiline(m):多行匹配;

元字符

代表出現(xiàn)次數(shù)的量詞元字符

    *   :   出現(xiàn)零到多次
    ?   :   出現(xiàn)0次或1次
    +   :   出現(xiàn)1到多次
   {n}  :   出現(xiàn)n次
   {n,} :   出現(xiàn)n到多次
  {n,m} :   出現(xiàn)n到m次

具有特殊意義的元字符

    \   :   轉(zhuǎn)義字符(兩個(gè)\\就表示兩個(gè)\\)
    ^   :   以某一個(gè)元字符開(kāi)始益兄,不占位置锻梳。(只對(duì)字符串的開(kāi)頭起作用)
    $   :   以某一個(gè)元字符結(jié)尾,不占位置净捅。(只對(duì)字符串的末尾起作用)
    .   :   除了\n(換行符)以外的任意字符
    ()  :   分組
   x|y  :   x或y中的一個(gè)
  [xyz] :   x或者y或者z中的一個(gè)
 [^xyz] :   除了x y z的任何一個(gè)字符
  [a-z] :   a-z之間的任何一個(gè)字符
 [^a-z] :   除了a-z的任何一個(gè)字符
    \d  :   一個(gè)0-9之間的數(shù)字
    \D  :   匹配一個(gè)非數(shù)字字符
    \b  :   一個(gè)邊界符:“er\b”可以匹配“never”中的“er”,但不能匹配“verb”中的“er”,單詞左右兩邊是邊界疑枯,-的左右兩邊也是邊界,所以會(huì)把zhu-feng-pei-xun當(dāng)作4個(gè)單詞蛔六,而我們想把它當(dāng)成一個(gè)單詞
    \n  :   匹配一個(gè)換行符荆永。
    \s  :   匹配一個(gè)空白字符 (空格废亭,制表符,換頁(yè)符)
    \w  :   數(shù)字具钥,字母滔以,下劃線(xiàn)中的任意一個(gè)字符
    ?:  :   只匹配不捕獲
    ?=  :   正向預(yù)查
    ?!  :   負(fù)向預(yù)查

正則中[]的特殊含義

1、里面出現(xiàn)的元字符一般都是代表本身意義的但是有一些依然表示符號(hào)本身的意思如[\d\w]
2氓拼、中括號(hào)中出現(xiàn)'-'代表兩種意思

  • [a-z0-9]:- 代表范圍連接符
  • [a-z_0-9-]:如果-的左右兩邊任何一邊沒(méi)有內(nèi)容那么’-‘代表本身的意思。

3抵碟、[]中出現(xiàn)的兩位數(shù)不代表本身意思桃漾,而是以一位數(shù)來(lái)解析,如[18]代表1或8兩個(gè)數(shù)字中的一個(gè)拟逮;

正則中()的作用

提高優(yōu)先級(jí)

正則中的分組撬统,也可以理解為一個(gè)大正則中的一個(gè)正則(包起來(lái)的部分是個(gè)一個(gè)整體);我們可以使用小括號(hào)改變一些默認(rèn)的優(yōu)先級(jí)敦迄。如(x|y)

分組引用

(\d)\1:\1代表引用和前面相同的數(shù)字恋追;

分組捕獲

正則捕獲的時(shí)候不僅可以把大正則匹配的內(nèi)容捕獲到,而且也會(huì)把小括號(hào)中的內(nèi)容捕獲到

常用的正則表達(dá)式編寫(xiě)

注意:正則中如果同時(shí)加入了^和 $表示只能是xxx罚屋,不加的話(huà)表示包含xxx苦囱,而且^只對(duì)字符串的開(kāi)頭起作用,$只對(duì)字符串的結(jié)尾起作用脾猛;

    reg= /^-?((\d)|([1-9]\d+))(\.\d+)?$/  有效數(shù)字正則

    reg=/^1\d{10}$/ 手機(jī)號(hào)驗(yàn)證

    //=>/^[\u4E00-\u9FA5]$/ 中文漢字的正則
    姓名的正則:
    reg = /^[\u4E00-\u9FA5]{2,10}$/;
    reg = /^[\u4E00-\u9FA5]{2,10}(·[\u4E00-\u9FA5]{2,10})?$/;
    
    郵箱正則
    /*
     * 以數(shù)字字母下劃線(xiàn)開(kāi)頭
     * @前面可以是 數(shù)字撕彤、字母、下劃線(xiàn)猛拴、-羹铅、. 這些符號(hào)
     * 不能把 -和. 連續(xù)出現(xiàn),出現(xiàn)一次后面必須跟數(shù)字字母下劃線(xiàn)
     *  
     * @后面的部分支持
     *   企業(yè)郵箱
     *   .com.cn 多域名情況
     */
    reg=/^\w+((-\w+)|(\.\w+))*@[A-Za-z0-9]+((\.|-)[A-Za-z0-9]+)*\.[A-Za-z0-9]+$/
    
    身份證:
    前六位:省市縣
    接下來(lái)八位 出生年+月+日
    接下來(lái)的兩位:沒(méi)什么用
    倒數(shù)第二位數(shù)字 奇數(shù)為男愉昆,偶數(shù)為女
    reg = /^(\d{6})(\d{4})(\d{2})(\d{2})\d{2}(\d)(\d|X)$/;

正則的捕獲

exec

正則的捕獲:reg.exec(str)
捕獲的內(nèi)容是一個(gè)數(shù)組职员,數(shù)組中的第一項(xiàng)是當(dāng)前正則捕獲的內(nèi)容,如果有小括號(hào)(),則第二項(xiàng)捕獲的是小括號(hào)里的內(nèi)容跛溉。

  • index:捕獲內(nèi)容在字符串中開(kāi)始的索引位置焊切。
  • input:捕獲的原始字符串。如果沒(méi)有匹配的返回null芳室;

1蛛蒙、(懶惰性)捕獲的特點(diǎn):執(zhí)行一次捕獲一次,每次執(zhí)行exec只捕獲第一個(gè)匹配的內(nèi)容渤愁。
為什么會(huì)存在懶惰性牵祟?

  • 每個(gè)正則都自帶lastIndex屬性:正則每一次捕獲在字符串中開(kāi)始查找的位置,默認(rèn)值為0抖格;
    我們手動(dòng)修改lastIndex的值也不會(huì)影響exec每次開(kāi)始查找的索引诺苹。

如何解決只捕獲第一個(gè)匹配(懶惰性)咕晋?

在正則末尾加一個(gè)修飾符"g"
原理:
修改lastIndex的值為上一次捕獲內(nèi)容之后的第一個(gè)字符的索引;加了g之后能保證下次捕獲第二個(gè)匹配的內(nèi)容;
通過(guò)加g 每次捕獲結(jié)束后收奔,lastIndex的值都會(huì)改變成最新的值掌呜,下次捕獲從最新的位置開(kāi)始找。如果沒(méi)有找到符合的坪哄,則返回null质蕉;
如何解決exec執(zhí)行一次捕獲一次?
1翩肌、

//我的方法
RegExp.prototype.myExec=function(){
var str=arguments[0]||'',ary=this.exec(str),ary1=[];
if(this.global!==true)return ary;
while(ary){
ary1=ary1.concat(ary);
ary=this.exec(str);
}
return ary1;
}
//老師的方法
RegExp.prototype.myExec=function () {
var str=arguments[0]||'', ary=this.exec(str),result=[];
if(!this.global)return ary;
while (ary){
result.push(ary);
ary=this.exec(str);
}
return result;
}

###match
>用字符串方法方法實(shí)現(xiàn)多次捕獲
str.match(reg)
>1模暗、如果正則中加了修飾符g,那么執(zhí)行一次就可以把所有匹配的結(jié)果捕獲到
>2念祭、如果不加g兑宇,那么只捕獲第一次匹配的結(jié)果。返回一個(gè)數(shù)組粱坤,數(shù)組中是捕獲的每一項(xiàng)隶糕;
`[局限性]`
>在分組捕獲中,
>如果正則不加修飾符g站玄,
> - 那么match和exec一樣枚驻,可以捕獲到小分組的內(nèi)容。

>如果正則加了修飾符g
> - match只能捕獲到大正則匹配的內(nèi)容株旷,而對(duì)于小分組匹配的內(nèi)容是無(wú)法捕獲到的测秸;

`注意`:由于test和exec的原理相同,如果加了g灾常,都是修改lastIndex值來(lái)匹配或者捕獲霎冯,所以使用test和exec都會(huì)修改lastIndex的值,所以使用exec捕獲之前最好不要使用test钞瀑;

用test也可以捕獲符合的字符串
    
    reg.test(str);
    RegExp.$1//只能捕獲第1個(gè)小分組里面的內(nèi)容
    RegExp.$2//只能捕獲第2個(gè)小分組里面的內(nèi)容
    RegExp.$3//只能捕獲第2個(gè)小分組里面的內(nèi)容
    同reg.exec(str);也能使用RegExp.$1來(lái)捕獲第1個(gè)小分組
    RegExp.$1//只能捕獲第1個(gè)小分組里面的內(nèi)容
    RegExp.$2//只能捕獲第2個(gè)小分組里面的內(nèi)容
###所有的支持正則的方法都可以實(shí)現(xiàn)正則的捕獲(一般都是字符串的方法)
>字符串中常用的支持正則的方法:
>- match
>- replace
>- split:如果給的正則中包含小分組沈撞,那么會(huì)把小分組中的內(nèi)容也捕獲到;

>?:只匹配不捕獲雕什, 只能放在小分組的開(kāi)頭缠俺。如果加在分組中邻辉,那么只會(huì)匹配該分組中的內(nèi)容陈瘦,而不會(huì)捕獲
>/(?:&|=)/

>計(jì)算是第幾個(gè)分組的時(shí)候欠肾,我們從左向右找'('即可

    var reg = /^-?(\d|([1-9]\d+))(\.\d+)?$/;//=>計(jì)算是第幾個(gè)分組的時(shí)候逝她,我們從左向右找 ( 即可
##replace(第二個(gè)參數(shù)支持直接在字符串中使用$1-9)
>替換字符串
>在不使用正則的情況下,每次執(zhí)行只能替換第一個(gè)匹配的字符串尊浪,而且每次執(zhí)行都是從字符串索引為0的位置開(kāi)始查找
>`第一個(gè)參數(shù)為正則時(shí)`偶妖,正則捕獲幾次肌访,就替換幾次,換成函數(shù)也同理盒使,正則捕獲幾次崩掘,函數(shù)就執(zhí)行幾次,函數(shù)中返回的是什么少办,就相當(dāng)于把正則捕獲的內(nèi)容替換成什么苞慢。
>`第二個(gè)參數(shù)為函數(shù)時(shí)`,正則捕獲幾次英妓,函數(shù)就執(zhí)行幾次挽放,函數(shù)執(zhí)行的時(shí)候還會(huì)默認(rèn)的傳入三個(gè)參數(shù):
>context(捕獲的內(nèi)容)
>index(捕獲內(nèi)容在字符串中的開(kāi)始索引)
>input(原始的字符串)

    str.replace(/珠峰/g,function(context,index,input){
        arguments[0]大正則匹配的內(nèi)容
        //如果正則中有分組的話(huà)
        arguments[1]第1個(gè)小分組匹配的內(nèi)容
        arguments[2]第2個(gè)小分組匹配的內(nèi)容
        …………直到小分組的內(nèi)容顯示完
        argument[n]每一次捕獲的開(kāi)始索引
        argument[n+1]原始字符串
        return 的是什么就會(huì)把正則每次捕獲的內(nèi)容替換成什么
    })
    需求:把每個(gè)單詞的首字母替換為大寫(xiě),zhu-feng-pei-xun當(dāng)成一個(gè)單詞
    var str='my name is zhu-feng-pei-xun,i am 8 years old,i am qian duan pei xun no1!';
    var reg=/[a-zA-Z-]+/g;
    str=str.replace(reg,function () {
        return arguments[0].slice(0,1).toUpperCase()+arguments[0].slice(1);
    })
    console.log(str);
###時(shí)間格式化字符串
方法1

    var str = '2017-11-07 16:37:00';
    //=>'2017年11月07日 16時(shí)37分00秒'

    //=>使用正則實(shí)現(xiàn)
    //1蔓纠、執(zhí)行一次捕獲操作辑畦,得到需要的六個(gè)結(jié)果
    var reg = /^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2}):(\d{1,2})$/g;
    // str = str.replace(reg, function () {
    //     var arg = arguments;
    //     return arg[1] + '年' + arg[2] + '月' + arg[3] + '日 ' + arg[4] + '時(shí)' + arg[5] + '分' + arg[6] + '秒';
    // });
        str = str.replace(reg, '$1年$2月$3日 $4時(shí)$5分$6秒');//=>$1等價(jià)于第一個(gè)分組中獲取的內(nèi)容,類(lèi)似于上面代碼的arg[1]
    console.log(str);//=>'2017年11月07日 16時(shí)37分00秒'
方法2

    String.prototype.myformate=function () {
        var ary=this.match(/\d+/g);
        var temp=arguments[0]||'{0}年{1}月{2}日 {3}時(shí){4}分{5}秒';
        var reg=/\{(\d)\}/g;
        temp=temp.replace(reg,function () {
            var value=ary[arguments[1]]||'0';
            return value.length<2?'0'+value:value;
        })
        return temp;
    }

##16、OOP(面向?qū)ο缶幊趟枷?
###單例模式
>我們把對(duì)象數(shù)據(jù)類(lèi)型實(shí)現(xiàn)`把描述同一件事務(wù)的屬性或者特征歸納匯總在一起贺纲,以此避免全局變量沖突問(wèn)題`的方式和思想叫做:?jiǎn)卫O(shè)計(jì)模式;
>把描述同一件事務(wù)的屬性或者方法存放在某一個(gè)命名空間下褪测,多個(gè)命名空間中的屬性和方法是互不干擾的
```javascript
//=>單例模式
//1猴誊、singleton不僅僅是對(duì)象名了,在單例模式中侮措,singleton稱(chēng)之為 “命名空間(nameSpace)”
var singleton={
    xxx:xxx,
    ...
};

var singleton={
    nameSpace1:{
        xxx:xxx,
        ...
    },
    nameSpace2:{
        xxx:xxx,
        ...
    }
    ...
};

使用單例模式實(shí)現(xiàn)模塊化開(kāi)發(fā)

模塊化開(kāi)發(fā):把一個(gè)復(fù)雜頁(yè)面按照具體功能劃分成幾大塊懈叹,然后由不同的人分別去開(kāi)發(fā),這種模塊劃分的思想就是模塊化開(kāi)發(fā)功能分扎。

//=>項(xiàng)目主管(開(kāi)發(fā)人員):公共模塊
var utils={
    trim:function(){}
};

//=>陸永勇:搜索模塊
var searchModel={
    submit:function(){
        utils.trim();
    },
    ...
};

//=>唐元帥:天氣模塊
var weatherModel={
    setWeather:function(){},
    ...
};
//=>陳金廣:頻道模塊
var channelModel={
    show:function(){
       //=>在當(dāng)前的命名空間下調(diào)取其它命名空間的方法:指定好對(duì)應(yīng)的命名空間名字即可澄成,使用 [NameSpace].[property] 就可以操作了
        searchModel.submit();

        //=>調(diào)取本模塊中的一些方法,可以直接使用THIS處理即可:此方法中的THIS一般都是當(dāng)前模塊的命名空間
        this.setChannel();
    },
    setChannel:function(){},
    ...
};
channelModel.show();

高級(jí)單例模式

基于JS高階編程技巧惰性思想畏吓,來(lái)實(shí)現(xiàn)的單例模式墨状,并且可以把一些常用的設(shè)計(jì)模式(如:命令模式、發(fā)布訂閱模式菲饼、promise設(shè)計(jì)模式等)融合進(jìn)來(lái)肾砂,最后清晰的規(guī)劃我們的業(yè)務(wù)邏輯代碼,方便后期二次開(kāi)發(fā)和維護(hù)宏悦,這種設(shè)計(jì)思想綜合體就是高級(jí)單例模式镐确,也是最常用的。

var serchModel=(function(){
    function submit(){
    }
    return {
        init:function(){
            this.submit();
        }
    }
    })();
    searchModel.init();

對(duì)象饼煞、類(lèi)源葫、實(shí)例

對(duì)象:萬(wàn)物皆對(duì)象
類(lèi):對(duì)象的具體細(xì)分(按照屬性或特性細(xì)分的一些類(lèi)別)
實(shí)例:某一個(gè)類(lèi)中的具體事物

JS常用的內(nèi)置類(lèi)

數(shù)據(jù)類(lèi)型的類(lèi)

Number:每個(gè)數(shù)字或者NaN是它的一個(gè)實(shí)例
String:字符串類(lèi)
Boolean:布爾類(lèi)
Null
Undefined:瀏覽器屏蔽了我們操作null和udnefined這個(gè)類(lèi)
Object:對(duì)象類(lèi),每個(gè)對(duì)象數(shù)據(jù)類(lèi)型都是它的實(shí)例

  • Array:數(shù)組類(lèi)
  • RegExp:正則類(lèi)
  • Date:日期類(lèi)

Function:函數(shù)類(lèi)砖瞧,每個(gè)函數(shù)都是它的一個(gè)實(shí)例

元素對(duì)象或者元素集合的類(lèi)

HTMLCollection:元素集合類(lèi)

  • getElementsByTagName()
  • getElementsByClassName()
  • querySelectorAll

NodeList:節(jié)點(diǎn)集合類(lèi)

  • childNodes
  • getElementsByName()

HTMLDivElement
HTMLElement
Element(標(biāo)簽類(lèi))
Node(節(jié)點(diǎn)類(lèi)息堂,Element只是其中的一個(gè)元素節(jié)點(diǎn))

[圖片上傳失敗...(image-45ab-1541561653878)]

為什么getElementById的上下文只能是document?(即getElementById為什么只能通過(guò)document來(lái)調(diào)用)块促?

因?yàn)橹挥性贒ocument這個(gè)類(lèi)上才有g(shù)etElementById這個(gè)方法储矩,其他類(lèi)上(如:HTMLDivElement類(lèi))沒(méi)有g(shù)etElementById這個(gè)方法感耙,而document是HTMLDocument這個(gè)類(lèi)的一個(gè)實(shí)例,能通過(guò)document._proto_._proto_找到Document這個(gè)類(lèi)的原型上公有的getElementById方法。

[圖片上傳失敗...(image-585c72-1541561653878)]

基于面向?qū)ο髣?chuàng)建數(shù)據(jù)

創(chuàng)建方式:兩種

1.字面量創(chuàng)建方式

  • var obj={}持隧;

2.實(shí)例創(chuàng)建方式(構(gòu)造函數(shù)方式)

  • var obj=new Array();

1即硼、對(duì)于引用數(shù)據(jù)類(lèi)型來(lái)說(shuō),兩種創(chuàng)建方式是大致相同的屡拨,只不過(guò)只酥,兩種方法創(chuàng)建的語(yǔ)法不同。

兩種創(chuàng)建方式在核心意義上沒(méi)有差別呀狼,都是創(chuàng)建Array這個(gè)類(lèi)的一個(gè)實(shí)例裂允,但是在語(yǔ)法上是有區(qū)別的
1、字面量創(chuàng)建方式傳遞進(jìn)來(lái)什么哥艇,都是給數(shù)組每一項(xiàng)加入的內(nèi)容
2绝编、構(gòu)造函數(shù)創(chuàng)建方式
new Array(10):創(chuàng)建一個(gè)長(zhǎng)度為10的數(shù)組,數(shù)組中的每一項(xiàng)都是空
new Array('10'):如果只傳遞一個(gè)實(shí)參,并且實(shí)參不是數(shù)字貌踏,相當(dāng)于把當(dāng)前值作為數(shù)組的第一項(xiàng)存儲(chǔ)進(jìn)來(lái)
new Array(10,20,30):如果傳遞多個(gè)實(shí)參十饥,不是設(shè)置長(zhǎng)度,而是把傳遞的內(nèi)容當(dāng)做數(shù)組中的每一項(xiàng)存儲(chǔ)起來(lái)

2祖乳、對(duì)于基本數(shù)據(jù)類(lèi)型來(lái)說(shuō)逗堵,字面量方式創(chuàng)建出來(lái)的結(jié)果和實(shí)例方式創(chuàng)建出來(lái)的結(jié)果是有一定區(qū)別的,從嚴(yán)格意義上來(lái)講眷昆,只有實(shí)例創(chuàng)建出來(lái)的結(jié)果才是標(biāo)準(zhǔn)的對(duì)象蜒秤,數(shù)據(jù)類(lèi)型值也是標(biāo)準(zhǔn)的基本數(shù)據(jù)類(lèi)型,也是標(biāo)準(zhǔn)的內(nèi)置類(lèi)的實(shí)例亚斋;對(duì)于字面量方式創(chuàng)建出來(lái)的結(jié)果是基本數(shù)據(jù)類(lèi)型的值作媚,不是嚴(yán)格的實(shí)例,但是由于JS的松散特點(diǎn)帅刊,導(dǎo)致了可以使用 內(nèi)置類(lèi).prototype上提供的方法掂骏;

構(gòu)造函數(shù)設(shè)計(jì)模式

使用構(gòu)造函數(shù)方式,主要是為了創(chuàng)建類(lèi)和實(shí)例的厚掷,也就是基于面向?qū)ο笏枷雭?lái)實(shí)現(xiàn)一些需求

在JS中弟灼,當(dāng)我們使用new xxx()執(zhí)行函數(shù)的時(shí)候,此時(shí)的函數(shù)就不是普通的函數(shù)了冒黑,而是變?yōu)橐粋€(gè)類(lèi)田绑,返回的結(jié)果叫做當(dāng)前類(lèi)的實(shí)例,我們這種new xxx執(zhí)行的方式稱(chēng)之為構(gòu)造函數(shù)設(shè)計(jì)模式

function fn(){

}
new fn();

構(gòu)造函數(shù)執(zhí)行時(shí)new都干了些什么抡爹?

在new Fn()掩驱,執(zhí)行的時(shí)候,是先把函數(shù)執(zhí)行了,也就是后面的Fn()先執(zhí)行欧穴,形成一個(gè)私有作用域民逼,形參賦值變量提升,在變量提升完了之后涮帘,new操作符才起了作用拼苍,這個(gè)時(shí)候,瀏覽器開(kāi)始創(chuàng)建一個(gè)新的對(duì)象调缨,讓Fn中的this指向這個(gè)新創(chuàng)建的對(duì)象疮鲫,然后讓這個(gè)對(duì)象的_proto_指向Fn.prototype,然后JS代碼才開(kāi)始繼續(xù)往下執(zhí)行弦叶,開(kāi)始往新創(chuàng)建的對(duì)象當(dāng)中添加每個(gè)實(shí)例私有的屬性和方法俊犯。JS代碼執(zhí)行完成后,會(huì)默認(rèn)返回當(dāng)前創(chuàng)建的這個(gè)對(duì)象伤哺。

[圖片上傳失敗...(image-348e4d-1541561653878)]

普通函數(shù)執(zhí)行與構(gòu)造函數(shù)執(zhí)行的區(qū)別

構(gòu)造函數(shù)執(zhí)行的時(shí)候燕侠,也是先形成一個(gè)私有作用域,形參賦值立莉,變量提升绢彤,在代碼從上而下執(zhí)行之前,構(gòu)造函數(shù)有特殊的操作:瀏覽器會(huì)在當(dāng)前的作用域中默認(rèn)創(chuàng)建一個(gè)對(duì)象數(shù)據(jù)類(lèi)型的值桃序,并且會(huì)讓當(dāng)前函數(shù)中的this指向創(chuàng)建的這個(gè)對(duì)象杖虾。然后JS代碼再執(zhí)行烂瘫,代碼執(zhí)行完成后媒熊,即使函數(shù)中沒(méi)有寫(xiě)return,在構(gòu)造函數(shù)模式中:瀏覽器會(huì)默認(rèn)的把創(chuàng)建的對(duì)象返回到函數(shù)外面
<font color=red>總結(jié):</font>

  • 構(gòu)造函數(shù)執(zhí)行期間坟比,既具備函數(shù)執(zhí)行的一面芦鳍,也同時(shí)具備自己獨(dú)有的操作:在構(gòu)造函數(shù)執(zhí)行期間,瀏覽器會(huì)默認(rèn)創(chuàng)建一個(gè)對(duì)象葛账,這個(gè)對(duì)象就是當(dāng)前這個(gè)構(gòu)造函數(shù)(類(lèi))實(shí)例柠衅,函數(shù)執(zhí)行完成后,瀏覽器會(huì)默認(rèn)的把這個(gè)實(shí)例返回籍琳。所以new Fn()執(zhí)行菲宴,F(xiàn)n是一個(gè)類(lèi),返回的結(jié)果就是Fn這個(gè)類(lèi)的一個(gè)實(shí)例

構(gòu)造函數(shù)執(zhí)行后面的‘()’問(wèn)題

構(gòu)造函數(shù)執(zhí)行如果不需要傳遞參數(shù)趋急,函數(shù)后面的()可省略喝峦,如new Fn()可寫(xiě)為new Fn
注意

  • 如果要在new Fn之后直接調(diào)用實(shí)例的方法呜达,則必須要加小括號(hào)谣蠢,即必須寫(xiě)成new Fn().方法名

構(gòu)造函數(shù)模式的返回值問(wèn)題

構(gòu)造函數(shù)模式中默認(rèn)返回值是當(dāng)前的實(shí)例,如果有return,返回分2種情況:
1、return 后面是一個(gè)基本數(shù)據(jù)類(lèi)型的值眉踱,當(dāng)前實(shí)例是不變的挤忙,例如return 100;我們的返回值還是當(dāng)前類(lèi)的實(shí)例谈喳;
2册烈、return 后面是一個(gè)引用數(shù)據(jù)類(lèi)型的值,當(dāng)前實(shí)例會(huì)被返回的值給替換掉例如return {name:"珠峰"}我們的返回值就不再是當(dāng)前類(lèi)的實(shí)例了叁执,而是對(duì)象 {name:"珠峰"}茄厘;

A instanceof B

檢測(cè)某一個(gè)實(shí)例是否屬于這個(gè)類(lèi), 判斷A實(shí)例是否屬于B類(lèi)

attr in object

檢測(cè)attr是否是object的屬性,不管是私有屬性還是公有屬性只要存在谈宛,用in來(lái)檢測(cè)都是true

a.hasOwnProperty(attr)

attr是否是A實(shí)例的私有屬性

對(duì)象數(shù)據(jù)類(lèi)型的

  • 普通對(duì)象
  • 數(shù)組
  • 正則
  • Math數(shù)學(xué)函數(shù)
  • 一般類(lèi)的實(shí)例
  • 函數(shù)的prototype屬性(Function.prototype除外次哈,它是函數(shù)數(shù)據(jù)類(lèi)型的)
  • 實(shí)例的_proto_屬性

函數(shù)數(shù)據(jù)類(lèi)型的

  • 普通函數(shù)
  • 所有的類(lèi)(內(nèi)置類(lèi)和自定義類(lèi)都是)

原型鏈模式

基于構(gòu)造函數(shù)模式的原型鏈模式解決了方法或者屬性公有的問(wèn)題,把實(shí)例之間公有的屬性和方法寫(xiě)在當(dāng)前類(lèi)的prototype屬性上吆录;
1窑滞、每一個(gè)函數(shù)數(shù)據(jù)類(lèi)型都有一個(gè)天生自帶的屬性:prototype(原型),并且這個(gè)屬性的屬性值是一個(gè)對(duì)象數(shù)據(jù)類(lèi)型的值(<font color=red>Function.prototype是函數(shù)數(shù)據(jù)類(lèi)型的,但是它沒(méi)有prototype屬性(Function.prototype.prototype是undefined)恢筝。Array.prototype是一個(gè)數(shù)組</font>)哀卫,瀏覽器默認(rèn)為其開(kāi)辟一個(gè)堆內(nèi)存;
2撬槽、在瀏覽器給prototype開(kāi)辟的這個(gè)堆內(nèi)存中此改,瀏覽器天生給它加了一個(gè)constructor屬性(構(gòu)造函數(shù)),屬性值是當(dāng)前函數(shù)(類(lèi))本身侄柔;
3共啃、每一個(gè)對(duì)象數(shù)據(jù)類(lèi)型(普通對(duì)象、數(shù)組暂题、正則移剪、實(shí)例、protoype..)也天生自帶一個(gè)屬性:_proto_薪者,屬性值指向當(dāng)前實(shí)例所屬類(lèi)的原型(prototype);
(IE中屏蔽了對(duì)象的__proto__屬性纵苛,但是確實(shí)有,只是不讓我們使用而已)
4言津、Object是JS中所有對(duì)象數(shù)據(jù)類(lèi)型的基類(lèi)(最頂層的類(lèi))攻人;

原型鏈模式中的this

原型模式中的this分兩種情況:
1、 在類(lèi)中this.xxx=xxx;this->當(dāng)前類(lèi)的實(shí)例
2悬槽、 原型鏈中提供的私有(公有)方法中的this問(wèn)題:
總結(jié)看執(zhí)行的時(shí)候"."前面是誰(shuí)this就是誰(shuí)怀吻。具體操作步驟如下

  • 1、需要先確定this的指向(this)
  • 2陷谱、把this替換成對(duì)應(yīng)的的代碼
  • 3烙博、按照原型鏈查找的機(jī)制瑟蜈,一步步的查找結(jié)果

如何往原型中批量添加屬性和方法

重構(gòu)原型
讓某個(gè)構(gòu)造函數(shù)的原型指向我們自己開(kāi)辟的堆內(nèi)存,但是自己開(kāi)辟的堆內(nèi)存當(dāng)中是沒(méi)有constructor屬性的渣窜,所以要往自己開(kāi)辟的堆內(nèi)存中添加constructor屬性铺根,屬性值為當(dāng)前構(gòu)造函數(shù)本身;
缺點(diǎn):重構(gòu)原型后乔宿,會(huì)導(dǎo)致之前添加的屬性和方法都沒(méi)有了位迂,只能使用重構(gòu)之后添加的屬性和方法;
注意:

  • 不要忘了重構(gòu)之后要添加constructor屬性指向當(dāng)前構(gòu)造函數(shù)详瑞;
  • 內(nèi)置類(lèi)的原型不能重構(gòu)掂林,瀏覽器不允許我們這么做;
  • 重構(gòu)原型之前生成的實(shí)例的__proto__屬性值依然指向重構(gòu)之前的原型坝橡,而不是重構(gòu)之后的原型泻帮,只有在重構(gòu)原型之后生成的實(shí)例的__proto__屬性值才指向新的原型;

17计寇、面向?qū)ο蟮睦斫夂蛯W(xué)習(xí)繼承

面向?qū)ο缶幊?/h2>

它是一種編程思想锣杂,讓我們基于類(lèi)和實(shí)例的概念來(lái)編程開(kāi)發(fā)和學(xué)習(xí)。
類(lèi)的繼承番宁、封裝和多態(tài)

類(lèi)的封裝

把實(shí)現(xiàn)一個(gè)功能的代碼元莫,封裝在一個(gè)函數(shù)當(dāng)中,以后再想實(shí)現(xiàn)這個(gè)功能蝶押,只需要執(zhí)行這個(gè)方法即可踱蠢,不需要重復(fù)的編寫(xiě)代碼,減少了頁(yè)面中的代碼冗余度棋电,提高了代碼的重復(fù)利用率茎截,實(shí)現(xiàn)了低耦合高內(nèi)聚的思想

類(lèi)的多態(tài)

一個(gè)類(lèi)的多種形態(tài):重載、重寫(xiě)离陶;
[重載]
方法名相同稼虎,參數(shù)不同衅檀,叫做方法的重載
JS中沒(méi)有嚴(yán)格意義上的重載招刨,如果方法名相同,那么就會(huì)保留最后一個(gè)方法哀军,和傳遞的參數(shù)沒(méi)有關(guān)系沉眶;
JS中的重載:根據(jù)傳遞的實(shí)參不同,來(lái)實(shí)現(xiàn)不同的功能杉适』丫螅可以把這種方法叫做重載。
[重寫(xiě)]
JS中的重寫(xiě):子類(lèi)重寫(xiě)父類(lèi)的方法

類(lèi)的繼承

子類(lèi)繼承父類(lèi)的一些屬性和方法

原型繼承

<font color=red>原理</font>:讓子類(lèi)的原型指向父類(lèi)的一個(gè)實(shí)例(很少單獨(dú)使用)

    Son.prototype=new Parent();
    /繼承父類(lèi)之后猿推,需要手動(dòng)添加constructor屬性
    Son.prototype.constructor=Son;

<font color=red>特點(diǎn)</font>:它是把父類(lèi)中私有+公有的屬性和方法的都繼承到了子類(lèi)的原型上(子類(lèi)公有的)
<font color=red>核心</font>:原型繼承是讓子類(lèi)和父類(lèi)之間增加了原型鏈的連接關(guān)系片习,以后子類(lèi)的實(shí)例想要父類(lèi)中的方法捌肴,需要利用原型鏈查找機(jī)制一級(jí)一級(jí)向上查找來(lái)使用
<font color=red>原型繼承存在的問(wèn)題:</font>

  • 1、子類(lèi)的原型指向了父類(lèi)的一個(gè)實(shí)例藕咏,如果實(shí)例的某個(gè)屬性的值是引用數(shù)據(jù)類(lèi)型状知,那么我生成子類(lèi)的一個(gè)實(shí)例f,我通過(guò)f來(lái)修改子類(lèi)公有的這個(gè)引用數(shù)據(jù)類(lèi)型的值孽查,那么子類(lèi)的其他實(shí)例也會(huì)受影響饥悴;
  • 2、不能向父類(lèi)的構(gòu)造函數(shù)傳遞參數(shù)盲再。如果父類(lèi)給其實(shí)例定義的私有屬性的值跟傳入的參數(shù)有關(guān)系西设,那么子類(lèi)繼承過(guò)來(lái)之后,所有子類(lèi)實(shí)例的公有屬性的值都是一樣的答朋,

call繼承

<font color=red>原理</font>:把父類(lèi)當(dāng)作普通函數(shù)在子類(lèi)中執(zhí)行贷揽,修改函數(shù)中的this為子類(lèi)的實(shí)例。

function A(){
    this.x=100;
}
function B(){
//一般都把call繼承放在子類(lèi)函數(shù)體中的第一行,這樣做的好處就是子類(lèi)私有的可以替換掉繼承過(guò)來(lái)的結(jié)果梦碗;
    A.call(this);
    this.y=200
}

<font color=red>特點(diǎn)</font>:把父類(lèi)私有的屬性和方法克隆一份一模一樣的作為子類(lèi)私有的屬性(父類(lèi)公有的無(wú)法繼承)

寄生組合式繼承(call繼承+Object.create繼承)

<font color=red>總結(jié)</font>:寄生組合式繼承完成了一個(gè)需求

  • 子類(lèi)公有繼承了父類(lèi)公有的
  • 子類(lèi)私有繼承了父類(lèi)私有的
  • 而且子類(lèi)還可以擴(kuò)展自己的實(shí)例公有的屬性和方法(擴(kuò)展到創(chuàng)建的空對(duì)象上)擒滑,而不影響到父類(lèi)

Object.create():創(chuàng)建一個(gè)空對(duì)象,并把傳入的參數(shù)當(dāng)作空對(duì)象的原型叉弦;
<font color=red>原理</font>:把父類(lèi)當(dāng)作函數(shù)在子類(lèi)中執(zhí)行丐一,修改函數(shù)中的this為子類(lèi)的實(shí)例。用Object.create()創(chuàng)建空對(duì)象淹冰,并把傳入的參數(shù)當(dāng)作空對(duì)象的原型库车,把子類(lèi)的原型指向空對(duì)象的原型。

function A(){
    this.x=100;
}
function B(){
    this.y=200
}
//創(chuàng)建一個(gè)空對(duì)象樱拴,讓傳入的參數(shù)當(dāng)作空對(duì)象的原型柠衍,然后讓B的原型指向這個(gè)空對(duì)象;
B.prototype=Object.create(A.prototype);
//為了保證構(gòu)造函數(shù)的完整性,我們要給子類(lèi)的原型手動(dòng)設(shè)置constructor屬性值
B.prototype.constructor=B;
//Object.create在IE低版本不兼容晶乔,所以我們要自己模擬一個(gè)create方法珍坊。
Object.myCreate=function(){
    var Fn=new Function();
    Fn.prototype=argument[0];
    return new Fn();
}
//以下寫(xiě)法兼容所有瀏覽器;
B.prototype=Object.myCreate(A.prototype);

<font color=red>特點(diǎn)</font>:把父類(lèi)私有的給子類(lèi)私有,把父類(lèi)公有的給子類(lèi)公有正罢。

ES6中的類(lèi)和繼承

ES6中的繼承相當(dāng)于寄生組合式繼承

class Father{//定義一個(gè)類(lèi)阵漏;
    constructor(name,age){//構(gòu)造函數(shù)定義實(shí)例的私有屬性
        this.name=name;
        this.age=age;
    }
    getName(){//公有的函數(shù)和方法
        console.log(this.name,this.age);
    }
    static like(){//static后寫(xiě)Father當(dāng)做對(duì)象時(shí)的私有屬性
        console.log("我是Father函數(shù)的私有屬性")
    }
}
class Son extends Father{//子類(lèi)Son繼承父類(lèi)Father
    constructor(name,age,color){
    注意:super()只能用在子類(lèi)的構(gòu)造函數(shù)之中,用在其他地方會(huì)報(bào)錯(cuò)
        super(name,age);//super中的參數(shù)相當(dāng)于把父類(lèi)當(dāng)作普通函數(shù)執(zhí)行時(shí)傳遞給普通函數(shù)的參數(shù)
    //下面為子類(lèi)的私有屬性
        this.color=color;
    }
    //下面為子類(lèi)公有的方法
    getColor(){
        console.log(this.color)
    }
    static my(){//static后寫(xiě)的是把Son當(dāng)做對(duì)象時(shí)的私有屬性
        console.log("我是Son函數(shù)的私有屬性")
    }
}
關(guān)于super的兩種情況:
注意翻具,使用super的時(shí)候履怯,必須顯式指定是作為函數(shù)、還是作為對(duì)象使用裆泳,否則會(huì)報(bào)錯(cuò)叹洲。
1、作為函數(shù)執(zhí)行時(shí):
    只能在子類(lèi)的構(gòu)造函數(shù)中第一行寫(xiě)super()工禾,此時(shí)就相當(dāng)于Father.call(this);否則會(huì)報(bào)錯(cuò)(比如在子類(lèi)的公有方法中執(zhí)行super);
2运提、作為普通對(duì)象調(diào)用時(shí)
    在子類(lèi)的普通方法中(公有方法或私有方法)蝗柔,super指向父類(lèi)的原型,相當(dāng)于Father.prototype民泵,而通過(guò)super.getName(),getName方法中的this依然是子類(lèi)的實(shí)例诫咱,而不是super。
    在子類(lèi)的靜態(tài)方法中(把子類(lèi)當(dāng)作對(duì)象添加的方法)洪灯,指向父類(lèi)坎缭。
    

為什么要手動(dòng)修改constructor?

var a,b;
(function(){
  function A (arg1,arg2) {
    this.a = 1;
    this.b=2; 
  }

  A.prototype.log = function () {
    console.log(this.a);
  }
  a = new A();
  b = new A();
})()
a.log();
// 1
b.log();
// 1

a,b签钩,他們同為類(lèi)A的實(shí)例掏呼。因?yàn)锳在閉包里,所以現(xiàn)在我們是不能直接訪(fǎng)問(wèn)A的铅檩,那如果我想給類(lèi)A增加新方法怎么辦憎夷?
這個(gè)時(shí)候就可以通過(guò)a.constructor.prototype 來(lái)給其所屬類(lèi)添加公有的屬性和方法了

18、JS中的DOM盒子模型與一個(gè)盒子垂直水平居中

CSS中的盒子模型

css中的盒子模型有兩種昧旨,分別是 ie 盒子模型和標(biāo)準(zhǔn) w3c 盒子模型

w3c中的CSS盒子模型

[圖片上傳失敗...(image-e9c57d-1541561653878)]

width拾给、height:不是盒子的寬高,而是盒子中內(nèi)容的寬度和高度
盒子的寬=width+padding(left+right)+border(left/right);

CSS3盒子模型與IE中的盒子模型

[圖片上傳失敗...(image-4b0dea-1541561653878)]

width和height不僅僅是內(nèi)容的寬度兔沃,而是代表整個(gè)盒子的寬度(已經(jīng)包含了padding和border)蒋得,以后修改的padding或者border,只會(huì)影響盒子中內(nèi)容的高度乒疏,盒子的大小不會(huì)改變

css3中的盒子模型屬性box-sizing

box{
    box-sizing:border-box;
}
box-sizing的可能值:content-box(default)额衙,border-box,inherit(從父類(lèi)繼承)。
content-box:border和padding不計(jì)算入width之內(nèi)怕吴,盒子的寬度=width+padding+border
border-box:border和padding計(jì)算入width之內(nèi)窍侧,盒子的寬度=width

如何選擇<font color="red">w3c盒子模型</font>?

在網(wǎng)頁(yè)的頂部加上 <font color="red">!DOCTYPE</font> 聲明。假如不加 doctype 聲明转绷,那么各個(gè)瀏覽器會(huì)根據(jù)自己的行為去理解網(wǎng)頁(yè)伟件,即 ie 瀏覽器會(huì)采用 ie 盒子模型去解釋你的盒子,而火狐會(huì)采用標(biāo)準(zhǔn) w3c 盒子模型解釋你的盒子议经,所以網(wǎng)頁(yè)在不同的瀏覽器中就顯示的不一樣了斧账。反之,假如加上了 doctype 聲明爸业,那么所有瀏覽器都會(huì)采用標(biāo)準(zhǔn) w3c 盒子模型去解釋你的盒子其骄,網(wǎng)頁(yè)就能在各個(gè)瀏覽器中顯示一致了亏镰。

JS盒模型屬性

通過(guò)JS盒子模型屬性獲取到的結(jié)果都是不帶單位的扯旷,而且只能是正 數(shù)(會(huì)默認(rèn)的進(jìn)行四舍五入),而且只有scrollTop和scrollLeft可讀寫(xiě)索抓,其他都是只讀屬性钧忽;

clientWidth毯炮、clientHeigit(內(nèi)容寬度+padding)

(只讀屬性,每次訪(fǎng)問(wèn)都會(huì)重新計(jì)算耸黑,最好用變量保存)
clientWidth:內(nèi)容寬度Width+左右填充padding
clientHeight:內(nèi)容高度height+上下填充padding
當(dāng)前盒子可視區(qū)域的寬度和高度
可視區(qū)域:內(nèi)容寬高+左右填充padding
和內(nèi)容是否溢出桃煎,以及是否設(shè)置了overflow:hidden沒(méi)有關(guān)系

document.documentElement.clientWidth  || document.body.clientWidth:
  • 獲取當(dāng)前瀏覽器可視窗口(一屏幕)的寬度

clientTop、clientLeft(盒子邊框的高度和寬度)

clientTop:盒子上邊框的寬度相當(dāng)于border-top
clientLeft:盒子左邊框的寬度相當(dāng)于border-left
獲取的就是邊框的寬度

offsetWidth大刊、offsetHeight(內(nèi)容寬度+padding+border)

只讀屬性
offsetWidth:盒子寬度+pading+border
offsetHeight:盒子高度+pading+border
在clientWidth和clientHeight的基礎(chǔ)上加上了左右或者上下邊框的寬度为迈,和內(nèi)容是否溢出也沒(méi)關(guān)系;

offsetParent缺菌、offsetLeft葫辐、offsetTop

offsetParent:當(dāng)前元素的父級(jí)參照物(在同一個(gè)平面中,最外層的元素是里面所有元素的父級(jí)參照伴郁,和HTML層級(jí)結(jié)構(gòu)沒(méi)有必然的聯(lián)系耿战。一個(gè)頁(yè)面中所有的父級(jí)參照物都是body。標(biāo)準(zhǔn)流中為body)
<font color=red>父級(jí)參照物可通過(guò)position: absolute relative fixed來(lái)改變焊傅;三個(gè)中任何一個(gè)都可以改變父級(jí)參照物剂陡,但是只能改變定位元素子元素的父級(jí)參照物,定位的元素的父級(jí)參照物不改變狐胎。<font>

**offsetLeft:當(dāng)前元素距離其父級(jí)參照物的內(nèi)邊框的左偏移量 **
offsetTop:當(dāng)前元素距離其父級(jí)參照物的內(nèi)邊框的上偏移量
在IE8當(dāng)中鸭栖,是從當(dāng)前元素的外邊框距離其父級(jí)參照物的外邊框的偏移量
當(dāng)前元素的外邊框距離父級(jí)元素參照物內(nèi)邊框的偏移量,父級(jí)參照物默認(rèn)為body

scrollWidth握巢、scrollHeight纤泵、scrollTop、scrollLeft

[沒(méi)有內(nèi)容溢出時(shí)]
獲取的結(jié)果和clientWidth镜粤、clientHeight是一樣的

[有內(nèi)容溢出的時(shí)候]

  • scrollHeight:真實(shí)內(nèi)容高度+上填充padding(因?yàn)閮?nèi)容溢出下padding已經(jīng)計(jì)算了所以不用加)
  • scrollWidth:真實(shí)內(nèi)容寬度+左填充padding(因?yàn)閮?nèi)容溢出右padding已經(jīng)計(jì)算了所以不用加)

scrollLeft/scrollTop:橫向或縱向滾動(dòng)條卷去的寬度/高度(只有這兩個(gè)可讀寫(xiě))
存在最大最小值:最小為0捏题,最大為卷去的高度/寬度 - 一屏幕的高度clientHeight

[圖片上傳失敗...(image-6e371a-1541561653878)]

獲取元素具體的樣式值

1、ele.style.xxx

  • 獲取當(dāng)前元素所有寫(xiě)在行內(nèi)樣式上的值(只有寫(xiě)在行內(nèi)樣式上的才能獲取到)

2肉渴、getComputedStyle/currentStyle(IE8及以下使用currentStyle)都帶單位公荧;

  • getComputedStyle(ele,當(dāng)前元素的偽類(lèi)一般為null)同规,獲取的是一個(gè)對(duì)象數(shù)據(jù)類(lèi)型的值循狰,如果需要獲取某一項(xiàng)需要用點(diǎn)或者[]來(lái)訪(fǎng)問(wèn)獲取結(jié)果的某個(gè)屬性
  • ele.currentStyle (currentStyle是元素的一個(gè)屬性,而不是一個(gè)方法)獲取結(jié)果也是對(duì)象數(shù)據(jù)類(lèi)型的券勺,獲取某一項(xiàng)也要通過(guò)點(diǎn)或者[]來(lái)訪(fǎng)問(wèn)绪钥;

這兩個(gè)屬性獲取的結(jié)果都是字符串;

如何讓一個(gè)盒子水平垂直居中

1关炼、用CSS

使用定位程腹,需要知道盒子的具體寬高(兼容IE低版本)
position:absolute
top:50%
left:50%
margin:-高度的一半px 0 0 -寬度的一半px;


使用定位:不需要知道盒子的寬和高(不兼容IE低版本)
position:absolute儒拂;
top:0寸潦;
left:0色鸳;
right:0;
bottom:0见转;
margin:auto命雀;

如何讓一個(gè)寬度不固定的塊級(jí)元素居中?
修改display為inline-block
父級(jí)的text-align:center

使用css3方法實(shí)現(xiàn)
position: absolute;
top:50%;
left: 50%;
transform: translateX(-50%) translateY(-50%);

2、用JS方法實(shí)現(xiàn)

首先讓盒子先絕對(duì)定位斩箫,然后設(shè)置盒子的left和top值即可
left=(當(dāng)前瀏覽器窗口的寬度-內(nèi)容的寬度)/2+'px'
        clientWidth-  offsetWidth
left=((document.documentElement.clientWidth || document.body.clientWidth)-ele.offsetWidth)/2+'px'
top=(當(dāng)前瀏覽器窗口的高度-內(nèi)容的高度)/2+'px'
left=((document.documentElement.clientHeight || document.body.clientHeight)-ele.offsetHeight)/2+'px'

19吏砂、JS中的定時(shí)器與異步編程

setTimeout(fn,interval)

設(shè)定一個(gè)定時(shí)器,到達(dá)指定時(shí)間之后執(zhí)行對(duì)應(yīng)的方法(執(zhí)行一次就結(jié)束了)乘客;

setInterval(fn,interval)

設(shè)置一個(gè)定時(shí)器赊抖,每間隔多少時(shí)間執(zhí)行一次fn,直到定時(shí)器清除為止(執(zhí)行很多次)

兩個(gè)定時(shí)器的區(qū)別

共同點(diǎn):
設(shè)置定時(shí)器時(shí)都會(huì)有一個(gè)返回值寨典,代表當(dāng)前是在瀏覽器中設(shè)置的第幾個(gè)定時(shí)器(返回的是定時(shí)器的序號(hào)氛雪,不管是setTimeout還是setInterval,)只要遇到這兩個(gè)其中一個(gè)耸成,就算一個(gè)新的定時(shí)器报亩,定時(shí)器的序號(hào)就會(huì)加1,即使清除了設(shè)置的定時(shí)器井氢,也不會(huì)重新計(jì)算序號(hào)弦追。
不同點(diǎn):
setTimeout是隔一段時(shí)間之后執(zhí)行一次函數(shù)
setInterval是每隔一段時(shí)間之后都執(zhí)行一次函數(shù);

用clearTimeout和clearInterval都可以清除兩個(gè)中任何一個(gè)定時(shí)器花竞,傳入的參數(shù)為定時(shí)器的序號(hào)劲件;

為什么我們要手動(dòng)清除定時(shí)器?

定時(shí)器也是一個(gè)函數(shù)约急,函數(shù)執(zhí)行完成后零远,返回了一個(gè)基本數(shù)據(jù)類(lèi)型值(定時(shí)器的序列號(hào))。沒(méi)有產(chǎn)生堆內(nèi)存的話(huà)就會(huì)在空閑時(shí)間被銷(xiāo)毀掉厌蔽,但是為什么setTimeout不會(huì)自動(dòng)銷(xiāo)毀牵辣?
因?yàn)楫?dāng)創(chuàng)建一個(gè)定時(shí)器的時(shí)候,瀏覽器會(huì)同時(shí)開(kāi)啟一個(gè)監(jiān)聽(tīng)者奴饮,當(dāng)setTimeout執(zhí)行完成后纬向,監(jiān)聽(tīng)者始終知道這個(gè)定時(shí)器的地址,所以不能銷(xiāo)毀戴卜,我們要手動(dòng)去清除定時(shí)器逾条。我們手動(dòng)清除的時(shí)候其實(shí)就是在切斷定時(shí)器和監(jiān)聽(tīng)者之間的聯(lián)系;這樣定時(shí)器就會(huì)被銷(xiāo)毀掉投剥;

定時(shí)器中的this問(wèn)題

不管在哪執(zhí)行师脂,定時(shí)器函數(shù)中的this是window;
var obj={
    fn:function(){
        //this:obj
        setTimeout(function(){
            //=>this:window 不管在哪執(zhí)行,定時(shí)器中的this是window
        },1000);
        
        //=>想讓定時(shí)器函數(shù)中的this是obj,使用bind方法改變?yōu)閛bj
        setTimeout(function(){
            //=>this:obj
        }.bind(this),1000);
        //也可以用變量保存的方式來(lái)改變this
        var _this=this;
        setTimeout(function(){
            //=>_this:obj
            _this.name 

='xxx';
        },1000);

        setTimeout(()=>{
            //=>this:obj 箭頭函數(shù)中的this繼承宿主環(huán)境(上級(jí)作用域中)的this
        },1000);
    }
};
obj.fn();

同步編程和異步編程

JS是單線(xiàn)程的危彩,當(dāng)前的任務(wù)沒(méi)有完成攒磨,下面的任務(wù)是不進(jìn)行處理的(同步的)

同步編程

當(dāng)前的事情沒(méi)有完成泳桦,繼續(xù)處理當(dāng)前的事情,只有當(dāng)前的事件完成了,才會(huì)去做下一件事情熙含。(JS中大部分都是同步編程的)如for循環(huán)

異步編程

規(guī)劃一件事情粗梭,但不是當(dāng)前馬上去執(zhí)行這件事,需要一定時(shí)間之后再執(zhí)行浮毯,不會(huì)等到時(shí)間到了完疫,任務(wù)執(zhí)行完了,才繼續(xù)完成下面的任務(wù)债蓝。而是把它放到等待任務(wù)隊(duì)列中壳鹤,同時(shí)開(kāi)始計(jì)算等待時(shí)間,繼續(xù)執(zhí)行主任務(wù)隊(duì)列中的任務(wù)饰迹,只有主任務(wù)隊(duì)列中的任務(wù)都完成了芳誓,再到等待任務(wù)隊(duì)列當(dāng)中,看哪個(gè)先到時(shí)間了啊鸭,就先執(zhí)行哪個(gè)锹淌。如果主任務(wù)隊(duì)列中的任務(wù)沒(méi)完成,不會(huì)去執(zhí)行等待任務(wù)隊(duì)列當(dāng)中的任務(wù)赠制;

JS中的異步編程

在JS中的異步編程只有四種:
1赂摆、定時(shí)器都是異步編程的
2、所有的事件綁定都是異步編程钟些、
3烟号、Ajax讀取數(shù)據(jù)的時(shí)候,我們一般都設(shè)置為異步編程
4政恍、回調(diào)函數(shù)也是異步編程

定時(shí)器是有最小等待時(shí)間的褥符,即使設(shè)置為0也不會(huì)馬上執(zhí)行,等待時(shí)間短的先執(zhí)行抚垃;

同步異步編程的核心原理

JS中有兩個(gè)任務(wù)隊(duì)列(存放任務(wù)列表的空間就是任務(wù)隊(duì)列)
1喷楣、主任務(wù)隊(duì)列:同步執(zhí)行任務(wù);(從上到下執(zhí)行)
2鹤树、等待任務(wù)隊(duì)列:存放異步的任務(wù)铣焊;
<font color=red>原理</font>:規(guī)劃一件事情,但不是當(dāng)前馬上去執(zhí)行這件事罕伯,需要一定時(shí)間之后再執(zhí)行曲伊,不會(huì)等到時(shí)間到了,任務(wù)執(zhí)行完了,才繼續(xù)完成下面的任務(wù)坟募。而是把它放到等待任務(wù)隊(duì)列中岛蚤,開(kāi)始計(jì)時(shí),繼續(xù)執(zhí)行下面的操作懈糯,只有主任務(wù)隊(duì)列中的任務(wù)都完成了涤妒,再到等待任務(wù)隊(duì)列當(dāng)中,看哪個(gè)先到時(shí)間了赚哗,就先執(zhí)行哪個(gè)她紫,如果都到時(shí)間了,那么就看哪個(gè)等待的時(shí)間短屿储,就先執(zhí)行哪一個(gè)贿讹。如果主任務(wù)隊(duì)列中的任務(wù)沒(méi)完成,不會(huì)去執(zhí)行等待任務(wù)隊(duì)列當(dāng)中的任務(wù)够掠;

JS中動(dòng)畫(huà)實(shí)現(xiàn)的原理

CSS3動(dòng)畫(huà)

在CSS3中提供了transition(過(guò)渡動(dòng)畫(huà))/animation(幀動(dòng)畫(huà))
優(yōu)勢(shì):
性能好民褂,實(shí)現(xiàn)起來(lái)簡(jiǎn)單,CSS能解決的動(dòng)畫(huà)絕對(duì)不用其他方式疯潭。
弊端:
不兼容大部分IE或者其他低版本瀏覽器(移動(dòng)端的動(dòng)畫(huà)一般都是基于CSS3來(lái)完成的)

JavaScript動(dòng)畫(huà)

在JS中實(shí)現(xiàn)動(dòng)畫(huà)常用的有:
1赊堪、使用定時(shí)器驅(qū)動(dòng)動(dòng)畫(huà),
2袁勺、使用requestAnimationFrame來(lái)完成的動(dòng)畫(huà)
而所謂的canvas動(dòng)畫(huà)基本上也是基于這兩種方案完成的(canvas本身是繪圖)

Flash動(dòng)畫(huà)

非常早的動(dòng)畫(huà)處理方案雹食,想要實(shí)現(xiàn)動(dòng)畫(huà),需要把這部分制作成Flash影片期丰,然后用Adobe Flash Player插件來(lái)播放群叶;現(xiàn)在一些簡(jiǎn)單的DOM動(dòng)畫(huà)都告別了flash的時(shí)代,影片的播放也可以基于H5中的audio或者video完成钝荡;

JS中基于定時(shí)器的動(dòng)畫(huà)運(yùn)動(dòng)的兩種形式

1街立、限定步長(zhǎng),不限制運(yùn)動(dòng)時(shí)間埠通;
2赎离、限定運(yùn)動(dòng)的總時(shí)間,不限制每一步走的長(zhǎng)度端辱;公式:

  • time為定時(shí)器走一次的時(shí)間梁剔,zTime為運(yùn)動(dòng)總的時(shí)間
  • 元素當(dāng)前所在位置=(time/zTime*總路程+起始位置)

時(shí)間消耗測(cè)試

1、此方法只能測(cè)試運(yùn)算時(shí)間在1毫秒以上的舞蔽,

  var startTime=new Date();
//需要測(cè)試消耗時(shí)間的代碼
console.log(new Date()-startTime);

2荣病、此方法可以測(cè)試運(yùn)算時(shí)間在1毫秒以下的

console.time()
//需要測(cè)試消耗時(shí)間的代碼
console.timeEnd()

20、JS中的回調(diào)函數(shù)

什么是回調(diào)函數(shù)

把一個(gè)函數(shù)當(dāng)作實(shí)參值傳遞給另外一個(gè)函數(shù)渗柿,在另外一個(gè)函數(shù)中執(zhí)行這個(gè)函數(shù)个盆,這種處理機(jī)制就是回調(diào)函數(shù)機(jī)制;
什么時(shí)候用到回調(diào)函數(shù)?
凡是在某一個(gè)函數(shù)的某一個(gè)階段需要完成某一件事情(而這件事情是不確定的)颊亮,都可以利用回調(diào)函數(shù)機(jī)制柴梆,把需要處理的事情當(dāng)作值傳遞進(jìn)來(lái)

function fn(num,callBack){
    typeof callBack==='function'?callBack():null;
    //也可以使用以下默認(rèn)方式(不過(guò)不嚴(yán)謹(jǐn):可能傳遞的不是函數(shù))
    callBack&&callBack()
}

1、回調(diào)函數(shù)可以被執(zhí)行多次终惑;
2绍在、還可以給callBack()傳遞參數(shù)值;
3狠鸳、還可以把回調(diào)函數(shù)中的this進(jìn)行修改揣苏;
4悯嗓、我們還可以接收回調(diào)函數(shù)執(zhí)行返回的值件舵;

    var ary=[12,23,34];
    ary.sort(funciton(a,b){
        /這里的function就是sort方法中的回調(diào)函數(shù)
    })

回調(diào)函數(shù)中的this問(wèn)題

回調(diào)函數(shù)中的 this一般都是window(嚴(yán)格模式下是undefined),原因:
我們一般執(zhí)行回調(diào)函數(shù)的時(shí)候都是直接執(zhí)行回調(diào)函數(shù)脯厨,沒(méi)有指定執(zhí)行主體铅祸,所以默認(rèn)情況下都是window;

定時(shí)器中的this問(wèn)題

只要不指明執(zhí)行主體合武,定時(shí)器中的this就是window.(嚴(yán)格模式下也是window)临梗;

關(guān)于Each循環(huán)方法的封裝

需求
兼容所有瀏覽器
類(lèi)似于JQ中的EACH方法,我們需要支持對(duì)數(shù)組稼跳,類(lèi)書(shū)組盟庞,純對(duì)象的遍歷任務(wù)
需要支持對(duì)原有數(shù)組的修改(回調(diào)函數(shù)中的返回值,可以修改原來(lái)數(shù)組中的某一項(xiàng)值)
在遍歷中汤善,通過(guò)回調(diào)函數(shù)返回值什猖,來(lái)結(jié)束當(dāng)前正在遍歷的操作(回調(diào)函數(shù)中返回false,我們應(yīng)該結(jié)束對(duì)數(shù)組的遍歷)

21红淡、ES6(JS新語(yǔ)法規(guī)范ES2016)基礎(chǔ)知識(shí)及核心原理

(詳細(xì)內(nèi)容請(qǐng)參考阮一峰大神的的ES6入門(mén):http://es6.ruanyifeng.com/#docs/intro)

使用Babel編譯ES6

1不狮、下載安裝babel
npm install babel-cli -g
我們之所以可以使用babel命令,是因?yàn)樵谌汁h(huán)境下會(huì)生成一些xxx.cmd的文件在旱,而這里的xxx就是可以在doc窗口中執(zhí)行的命令
執(zhí)行babel命令后摇零,可以完成一些編譯或者其他任務(wù),原因是執(zhí)行babel命令后桶蝎,會(huì)自動(dòng)加載處理任務(wù)的文件驻仅;
配置.babelrc文件,安裝在一些語(yǔ)言解析包
我們需要把.babelrc文件配置在當(dāng)前項(xiàng)目的根目錄下
注意:在電腦上不能直接創(chuàng)建沒(méi)有文件名的文件登渣,但是可以在webS中new->file來(lái)創(chuàng)建噪服,或者使用命令創(chuàng)建
1、babelrc這個(gè)后綴名在某些ws中是不識(shí)別的绍豁,我們需要設(shè)置關(guān)聯(lián)
2芯咧、在這個(gè)文件中編寫(xiě)內(nèi)容:

{
    "presets":[],//存的是我們編譯代碼時(shí)候需要依賴(lài)的語(yǔ)言解析包
    "plugins":[]//存的是我們編譯代碼時(shí)候需要依賴(lài)的插件信息
}

3、安裝依賴(lài)的語(yǔ)言解析包
在當(dāng)前項(xiàng)目的根目錄下安裝
npm install babel-preset-latest安裝最新已經(jīng)發(fā)布的語(yǔ)言標(biāo)準(zhǔn)解析模塊
npm install babel-preset-stage-2 安裝當(dāng)前還沒(méi)有發(fā)布但是已經(jīng)進(jìn)入草案的語(yǔ)言解析模塊
4、完成最后.babelrc

{
    "presets":[
        "latest",
        "stage-2"
    ],//存的是我們編譯代碼時(shí)候需要依賴(lài)的語(yǔ)言解析包
    "plugins":[]//存的是我們編譯代碼時(shí)候需要依賴(lài)的插件信息
}

三敬飒、使用命令編譯JS代碼
基本上所有支持命令操作的模塊都有一個(gè)命令
babel --help/babel -h 查看幫助
babel -V 查看版本號(hào)
babel -o 把某一個(gè)JS文件中的ES6代碼進(jìn)行編譯
babel -d 把某一個(gè)文件夾中所有的JS文件中的ES6代碼進(jìn)行編譯
babel -w 監(jiān)聽(tīng)文件中代碼的改變邪铲,當(dāng)代碼改變后,會(huì)自動(dòng)進(jìn)行編譯

ES6增加的語(yǔ)法

let&&const

letvar的區(qū)別

let 變量名=變量值
使用let創(chuàng)建變量和使用var創(chuàng)建變量的區(qū)別

  • 1无拗、用var聲明的變量會(huì)變量提升带到,用let聲明的變量不會(huì)進(jìn)行變量提升
用let創(chuàng)建變量
let xxx=xxx;
用let創(chuàng)建函數(shù)
let xxx=function(){}
創(chuàng)建自執(zhí)行函數(shù)
;(function(){
        
})();
  • 2、用let定義變量不允許在同一個(gè)作用域中重復(fù)聲明一個(gè)變量(只要當(dāng)前作用域中有這個(gè)變量英染,不管是用var還是用let聲明的揽惹,再用let聲明的話(huà)會(huì)報(bào)錯(cuò):不能重復(fù)聲明一個(gè)變量),但是可以重復(fù)定義(賦值)
    let i=10;
    let i=20;/會(huì)報(bào)錯(cuò)四康,
    i=20;重復(fù)賦值不會(huì)報(bào)錯(cuò)
  • 3搪搏、暫時(shí)性死區(qū):在代碼塊內(nèi),使用let命令聲明變量之前闪金,該變量都是不可用的疯溺。這在語(yǔ)法上,稱(chēng)為“暫時(shí)性死區(qū)”(temporal dead zone哎垦,簡(jiǎn)稱(chēng) TDZ)囱嫩。
if (true) {
  // TDZ開(kāi)始
  tmp = 'abc'; // ReferenceError,報(bào)錯(cuò)之后下面都不會(huì)輸出
  console.log(tmp); // ReferenceError,報(bào)錯(cuò)之后下面都不會(huì)輸出

  let tmp; // TDZ結(jié)束
  console.log(tmp); // undefined

  tmp = 123;
  console.log(tmp); // 123
}
//下面也會(huì)報(bào)錯(cuò)出現(xiàn)TDZ
console.log(typeof x); // ReferenceError
let x;
//作為比較如果一個(gè)變量根本沒(méi)有被聲明漏设,使用typeof反而不會(huì)報(bào)錯(cuò)墨闲。
console.log(typeof x);// "undefined"
  • 4、ES6語(yǔ)法創(chuàng)建的變量(let)存在塊級(jí)作用域
  • [ES5]
    window全局作用域
    函數(shù)執(zhí)行形成的私有作用域
  • [ES6]
    除了有ES5中的兩個(gè)作用域郑口,ES6中新增加塊級(jí)作用域(我們可以把塊級(jí)作用域理解為之前學(xué)習(xí)的私有作用域鸳碧,存在私有作用域和作用域鏈的一些機(jī)制)ES6中把大部分用{}包起來(lái)的都稱(chēng)之為塊級(jí)作用域;

const

const細(xì)節(jié)知識(shí)點(diǎn)和let類(lèi)似
const聲明的常量只要聲明就必須賦值,而且變量的值是一定的潘酗,不能被修改杆兵;

  • 注意:并不是變量的值不得改動(dòng),而是變量指向的那個(gè)內(nèi)存地址不得改動(dòng)仔夺。對(duì)于簡(jiǎn)單類(lèi)型的數(shù)據(jù)(數(shù)值琐脏、字符串、布爾值)缸兔,值就保存在變量指向的那個(gè)內(nèi)存地址日裙,因此等同于常量。但對(duì)于復(fù)合類(lèi)型的數(shù)據(jù)(主要是對(duì)象和數(shù)組)惰蜜,變量指向的內(nèi)存地址昂拂,保存的只是一個(gè)指針,const只能保證這個(gè)指針是固定的抛猖,至于它指向的數(shù)據(jù)結(jié)構(gòu)是不是可變的格侯,就完全不能控制了鼻听。因此,將一個(gè)對(duì)象聲明為常量必須非常小心联四。

const聲明的變量也存在暫時(shí)性死區(qū)撑碴,即只能在聲明的位置之后使用;

JS中創(chuàng)建變量的方式匯總

[ES5]

  • var :創(chuàng)建變量
    function:創(chuàng)建函數(shù)
    ES5中創(chuàng)建變量或者函數(shù):存在變量提升朝墩,重復(fù)聲明等特征醉拓;

[ES6]

  • let創(chuàng)建變量
    const:ES6中創(chuàng)建常量
    ES6中創(chuàng)建的變量或者常量:都不存在變量提升,也不可以重復(fù)聲明收苏,而且還存在塊級(jí)作用域亿卤;
    class:創(chuàng)建一個(gè)類(lèi)
    import:導(dǎo)入

ES6中的解構(gòu)賦值

按照原有值的結(jié)構(gòu),把原有值中的某一部分內(nèi)容快速獲取到(快速賦值給一個(gè)變量)

數(shù)組的解構(gòu)賦值

解構(gòu)賦值本身是ES6的語(yǔ)法規(guī)范鹿霸,使用什么關(guān)鍵字來(lái)聲明這些變量是無(wú)所謂的排吴,如果不用關(guān)鍵字來(lái)聲明,那么就相當(dāng)于給window添加的自定義屬性杜跷;(嚴(yán)格模式下必須使用關(guān)鍵字來(lái)聲明傍念,因?yàn)閲?yán)格模式下不允許出現(xiàn)不用關(guān)鍵字聲明的變量;)矫夷,如果解構(gòu)不到值葛闷,那么變量的值就是undefined;

let [a,b,c]=[12,23,34];
var [d,e,f]=[35,41,63];
console.log(a,b,c)//12,23,34;
console.log(d,e,f)//35,41,63;
[q,w,e]=[1,2,3];//相當(dāng)于給window添加了三個(gè)屬性:q,w,e值分別為1双藕,2淑趾,3;(嚴(yán)格模式下會(huì)報(bào)錯(cuò))

多維數(shù)組的解構(gòu)賦值忧陪,可以讓我們快速的獲取到需要的結(jié)果

let [a,b,c]=[[45,36],12,[23,43,[1,2[4,[8]]]]23,34];
console.log(a)//[45,36]
console.log(b)//12
console.log(c)//[23,43,[1,2,[4,[8]]]]
//數(shù)組中不需要解構(gòu)的值可用逗號(hào)(扣泊,)空開(kāi),一個(gè)逗號(hào)代表空開(kāi)一項(xiàng)
let [,,,A]=[12,23,45];
console.log(A)//undefined
let [,,B]=[12,23,45]
console.log(B)//45

在解構(gòu)賦值中嘶摊,支持?jǐn)U展運(yùn)算符即<font color=red>...</font>,只要用了擴(kuò)展運(yùn)算符延蟹,就相當(dāng)于新生成了一個(gè)數(shù)組或者對(duì)象,如果解構(gòu)不到值的話(huà)叶堆,新生成的數(shù)組或者對(duì)象為空阱飘,而不是undefined,但是擴(kuò)展運(yùn)算符必須放在末尾

let [a,...c]=[12,1,4,83,34];
console.log(a)//12
console.log(c)//[1,4,83,34];
let [a,...b,c]=[12,1,4,83,34];//會(huì)報(bào)錯(cuò)虱颗,擴(kuò)展運(yùn)算符只能放在末尾沥匈;

對(duì)象的解構(gòu)賦值

對(duì)象的簡(jiǎn)潔表示法:

const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}
// 等同于
const baz = {foo: foo};

對(duì)象的解構(gòu)與數(shù)組有一個(gè)重要的不同。數(shù)組的元素是按次序排列的忘渔,變量的取值由它的位置決定高帖;而對(duì)象的屬性沒(méi)有次序,變量必須與屬性同名畦粮,才能取到正確的值散址。
let { foo, bar } = { foo: "aaa", bar: "bbb" };
foo // "aaa"
bar // "bbb"

如果變量名與屬性名不一致乖阵,必須寫(xiě)成下面這樣。
let { foo: baz } = { foo: 'aaa', bar: 'bbb' };
baz // "aaa"
真正被賦值的是后者预麸,而不是前者义起。
let obj = { first: 'hello', last: 'world' };
let { first: f, last: l } = obj;
f // 'hello'
l // 'world'
first//error: first is not defined

如果要將一個(gè)已經(jīng)聲明的變量用于解構(gòu)賦值,必須非常小心师崎。
// 錯(cuò)誤的寫(xiě)法
let x;
{x} = {x: 1};//會(huì)報(bào)錯(cuò)
 因?yàn)?JavaScript 引擎會(huì)將{x}理解成一個(gè)代碼塊默终,從而發(fā)生語(yǔ)法錯(cuò)誤。只有不將大括號(hào)寫(xiě)在行首犁罩,避免 JavaScript 將其解釋為代碼塊齐蔽,才能解決這個(gè)問(wèn)題。
 // 正確的寫(xiě)法
let x;
({x} = {x: 1});
放在圓括號(hào)當(dāng)中就可以避免 JavaScript 將其解釋為代碼塊床估。

解構(gòu)賦值中支持指定默認(rèn)值

let [foo = true] = [];
console.log(foo);// true

let [x, y = 'b'] = ['a']; // x='a', y='b'
let [x, y = 'b'] = ['a', undefined]; // x='a', y='b'

var {x: y = 3} = {};
y // 3

var {x: y = 3} = {x: 5};
y // 5

解構(gòu)賦值的作用

1含滴、快速交換兩個(gè)變量的值

let a=12;
let b=13;
[a,b]=[b,a];
console.log(a);//13
console.log(b);//12

2、可以接收函數(shù)返回的多個(gè)值

let fn = function () {
    let a = 12,
        b = 13,
        c = 14;
    return [a, b, c];
};
let [a,b,c] = fn();
console.log(a, b, c);//=>12 13 14

<font color=red>...</font> 的三種身份:擴(kuò)展運(yùn)算符丐巫、展開(kāi)運(yùn)算符谈况、剩余運(yùn)算符

1、擴(kuò)展運(yùn)算符(注意递胧,在解構(gòu)賦值中碑韵,叫做擴(kuò)展運(yùn)算符,只能放在末尾)
只要用了擴(kuò)展運(yùn)算符缎脾,就相當(dāng)于新生成了一個(gè)數(shù)組或者對(duì)象祝闻,如果解構(gòu)不到值的話(huà),新生成的數(shù)組或者對(duì)象為空遗菠,而不是undefined联喘,但是擴(kuò)展運(yùn)算符必須放在末尾
    數(shù)組中的擴(kuò)展運(yùn)算符
    let [a,b,...c]=[12,1,4,83,34]
    console.log(a);//12
    console.log(b);//1
    console.log(c);//[4,83,34]
    對(duì)象中的擴(kuò)展運(yùn)算符
    let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
    console.log(x);//1
    console.log(y );//2
    console.log(z );//{ a: 3, b: 4 }
2、剩余運(yùn)算符
    function(...arg){
        ...arg就相當(dāng)于剩余運(yùn)算符辙纬,可以把傳遞的所有參數(shù)都獲取到豁遭,而且獲取到的是一個(gè)數(shù)組
    }
3、展開(kāi)運(yùn)算符
    function fn1(){
        
    }
    function fn2(){
        fn1(...arguments)
        ...arguments:這里的...就相當(dāng)于展開(kāi)運(yùn)算符贺拣,把a(bǔ)rguments展開(kāi)蓖谢,把里面的每一項(xiàng)分別傳遞給fn1當(dāng)作參數(shù),然后讓fn1執(zhí)行纵柿;
    }

箭頭函數(shù)

兩種寫(xiě)法:1蜈抓、表達(dá)式   2、函數(shù)體
表達(dá)式:
1.let fn=p=>p; 等價(jià)于 var fn=function(p){return p};
2.let fn=()=>n; 等價(jià)于 var fn=funciton(){return n};
3.let fn=(n,m)=>n+m;等價(jià)于 var fn=function(n,m){return n+m};
函數(shù)體:
let fn=(n,m)=>{
    var total=n+m;
    return total;
}

1昂儒、箭頭函數(shù)中不支持arguments,但是用 剩余運(yùn)算...arg 代替了arguments沟使,arg是一個(gè)數(shù)組,可以直接使用數(shù)組方法

let obj={
    name:'obj',
    fn(){
        //此方法的屬性名為fn渊跋,屬性值為一個(gè)函數(shù)腊嗡,和下面的sum寫(xiě)法是一樣的着倾;
    },
    sum:function () {
    
    }
};
let fn = (...arg)=> {
    /console.log(arguments);//=>Uncaught ReferenceError: arguments is not defined
    /=>不支持arguments,我們使用ES6中的剩余運(yùn)算符...來(lái)獲取傳遞的進(jìn)來(lái)的所有參數(shù)值(優(yōu)勢(shì):使用剩余運(yùn)算符接收到的結(jié)果本身就是一個(gè)數(shù)組,不需要再轉(zhuǎn)換了)
    /console.log(arg instanceof Array);//=>true
    return eval(arg.join('+'));
};
//=>也可以把FN簡(jiǎn)寫(xiě)成以下方式
//let fn = (...arg)=> eval(arg.join('+'));
console.log(fn(10, 20, 30, 40));

2燕少、箭頭函數(shù)中的this問(wèn)題卡者,可以默認(rèn)為箭頭函數(shù)中沒(méi)有this,在箭頭函數(shù)中出現(xiàn)的this都是宿主環(huán)境中(即上級(jí)作用域中)的this客们,與箭頭函數(shù)點(diǎn)之前的執(zhí)行主體沒(méi)有任何關(guān)系崇决;

ES6中的類(lèi)和繼承

ES6中創(chuàng)建類(lèi)和實(shí)例用class,創(chuàng)建出來(lái)的類(lèi)不存在變量提升底挫;
ES5中創(chuàng)建類(lèi)和實(shí)例恒傻,以及如何禁止用戶(hù)把類(lèi)當(dāng)做普通函數(shù)執(zhí)行:new.target

if (typeof new.target === 'undefined') {
  throw new SyntaxError(`當(dāng)前Person不能作為一個(gè)普通函數(shù)執(zhí)行,請(qǐng)使用new Person來(lái)執(zhí)行~~`);
  }
class Father {//定義一個(gè)類(lèi)建邓;
    constructor(name, age) {//構(gòu)造函數(shù)定義實(shí)例的私有屬性
        this.name = name;
        this.age = age;
    }

    getName() {//公有的函數(shù)和方法
        console.log(this.name + "的年齡是" + this.age + "歲了");
    }

    static like() {//static后面寫(xiě)的是把Father當(dāng)做對(duì)象時(shí)的私有屬性
        console.log("我是Father函數(shù)的私有屬性")
    }
}

class Son extends Father {//子類(lèi)Son繼承父類(lèi)Father
    constructor(name, age, color) {
        super(name, age);//繼承父類(lèi)的私有屬性盈厘,必須寫(xiě)
//下面為子類(lèi)的私有屬性
        this.color = color;
        super當(dāng)作對(duì)象調(diào)用時(shí),super就相當(dāng)于父類(lèi)的原型
    }

//下面為子類(lèi)公有的方法
    getColor() {
        console.log(this.color)
    }
}

字符串中新增加的方法

字符串.includes(val)

返回布爾值官边,字符串中是否包含val所代表的字符串沸手;

字符串.startsWith(val)

val是否在字符串的起始位置。

字符串.endsWith(val)

val是否在字符串的尾部注簿。

三個(gè)方法都返回一個(gè)布爾值

let s = 'Hello world!';
s.startsWith('Hello') // true
s.endsWith('!') // true
s.includes('o') // true

這三個(gè)方法都支持第二個(gè)參數(shù)契吉,表示開(kāi)始搜索的位置。

let s = 'Hello world!';
s.startsWith('world', 6) // true
s.endsWith('Hello', 5) // true
s.includes('Hello', 6) // false

上面代碼表示滩援,使用第二個(gè)參數(shù)n時(shí)栅隐,endsWith的行為與其他兩個(gè)方法有所不同。它 針對(duì)前n個(gè)字符玩徊,而其他兩個(gè)方法針對(duì)從第n個(gè)位置直到字符串結(jié)束。

repeat():返回一個(gè)新字符串谨究,表示將原字符串重復(fù)n次恩袱。

  'x'.repeat(3) // "xxx"
'hello'.repeat(2) // "hellohello"
'na'.repeat(0) // ""    

模版字符串

模版字符串,也是字符串胶哲,可以直接使用字符串中的方法畔塔;
模版字符串的空格和換行,都是被保留的鸯屿,如果想要消除空格可以使用trim方法澈吨;

$('#list').html(`
    <ul>
      <li>first</li>
      <li>second</li>
    </ul>
    `.trim());

模版字符串中可以嵌入變量,需要將變量寫(xiě)在${}中寄摆,大括號(hào)內(nèi)部可以放入任意的 JavaScript 表達(dá)式谅辣,可以進(jìn)行運(yùn)算,以及引用對(duì)象屬性婶恼。

  let x = 1;
let y = 2;
`${x} + ${y} = ${x + y}`
// "1 + 2 = 3"
`${x} + ${y * 2} = ${x + y * 2}`
// "1 + 4 = 5"
let obj = {x: 1, y: 2};
`${obj.x + obj.y}`
// "3"

模板字符串之中還能調(diào)用函數(shù)桑阶。

  function fn() {
  return "Hello World";
}
`foo ${fn()} bar`
// foo Hello World bar

ES6中新增加的迭代for of

forEach柏副,for,for in蚣录,for of的區(qū)別
forEach:不支持返回值割择,只是普通的循環(huán)遍歷
for in:key輸出的值為字符串類(lèi)型,包括把數(shù)組當(dāng)成對(duì)象添加的屬性也可以遍歷出來(lái)
for of:只返回具有數(shù)字索引的屬性萎河。這一點(diǎn)跟for...in循環(huán)也不一樣荔泳。(不能遍歷對(duì)象)

    let arr = [3, 5, 7];
    arr.foo = 'hello';
    
    for (let i in arr) {
    //for in是把a(bǔ)rr當(dāng)成對(duì)象遍歷,i是屬性名虐杯,包括arr的私有屬性
      console.log(i); // "0", "1", "2", "foo"
    }
    
    for (let i of arr) {
    //for of是把a(bǔ)rr當(dāng)成數(shù)組遍歷换可,i是數(shù)組中的每一項(xiàng)
      console.log(i); //  "3", "5", "7"
    }
    for of循環(huán)不會(huì)返回?cái)?shù)組arr的foo屬性
    如果只想拿到索引,可用keys()方法
    for (let index of arr.keys()) {
      console.log(index);
    }
    // 0
    // 1
    // 2
    如果兩個(gè)都想拿到厦幅,可用entries()方法
    for (let (index, elem) of arr.entries['?ntr?s]()) {
      console.log(index, elem);
    }
    // 0 "3"
    // 1 "5"
    // 2 "7"

ES6中的模塊導(dǎo)入和導(dǎo)出

//=>A模塊(在A模塊中導(dǎo)入B模塊)
import Temp,{lib} from "./B";//=>把導(dǎo)入的Temp中的部分屬性方法進(jìn)行解構(gòu)賦值
new Temp().init();
lib();//=>Temp.lib()
//=>B模塊(導(dǎo)出)
export default class Temp {
    init() {
        console.log(`hello world`);
    }
    static lib(){//=>Temp.lib
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末沾鳄,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子确憨,更是在濱河造成了極大的恐慌译荞,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,496評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件休弃,死亡現(xiàn)場(chǎng)離奇詭異吞歼,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)塔猾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)篙骡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人丈甸,你說(shuō)我怎么就攤上這事糯俗。” “怎么了睦擂?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,632評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵得湘,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我顿仇,道長(zhǎng)淘正,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,180評(píng)論 1 292
  • 正文 為了忘掉前任臼闻,我火速辦了婚禮鸿吆,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘述呐。我一直安慰自己惩淳,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,198評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布市埋。 她就那樣靜靜地躺著黎泣,像睡著了一般恕刘。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上抒倚,一...
    開(kāi)封第一講書(shū)人閱讀 51,165評(píng)論 1 299
  • 那天褐着,我揣著相機(jī)與錄音,去河邊找鬼托呕。 笑死含蓉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的项郊。 我是一名探鬼主播馅扣,決...
    沈念sama閱讀 40,052評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼着降!你這毒婦竟也來(lái)了差油?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,910評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤任洞,失蹤者是張志新(化名)和其女友劉穎蓄喇,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體交掏,經(jīng)...
    沈念sama閱讀 45,324評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡妆偏,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,542評(píng)論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了盅弛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片钱骂。...
    茶點(diǎn)故事閱讀 39,711評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖挪鹏,靈堂內(nèi)的尸體忽然破棺而出见秽,到底是詐尸還是另有隱情,我是刑警寧澤狰住,帶...
    沈念sama閱讀 35,424評(píng)論 5 343
  • 正文 年R本政府宣布张吉,位于F島的核電站,受9級(jí)特大地震影響催植,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜勺择,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,017評(píng)論 3 326
  • 文/蒙蒙 一创南、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧省核,春花似錦稿辙、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,668評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)赋咽。三九已至,卻和暖如春吨娜,著一層夾襖步出監(jiān)牢的瞬間脓匿,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,823評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工宦赠, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留陪毡,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,722評(píng)論 2 368
  • 正文 我出身青樓勾扭,卻偏偏與公主長(zhǎng)得像毡琉,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子妙色,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,611評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容

  • 這是16年5月份編輯的一份比較雜亂適合自己觀看的學(xué)習(xí)記錄文檔桅滋,今天18年5月份再次想寫(xiě)文章,發(fā)現(xiàn)簡(jiǎn)書(shū)還為我保存起的...
    Jenaral閱讀 2,752評(píng)論 2 9
  • Swift1> Swift和OC的區(qū)別1.1> Swift沒(méi)有地址/指針的概念1.2> 泛型1.3> 類(lèi)型嚴(yán)謹(jǐn) 對(duì)...
    cosWriter閱讀 11,097評(píng)論 1 32
  • 我一直覺(jué)得怎么樣身辨,才能最后讓原本善良的她丐谋,變得面目猙獰,直到懂得她的際遇栅表,我才漸漸體會(huì)笋鄙,并且很慶幸她并沒(méi)有跟我上床...
    柒小安閱讀 212評(píng)論 1 2