天天看點

js前端技術

一、前端技術

1、HTML

HTML(hypertext markup language)超文本标記語言,不同于程式設計語言。

超文本就是超出純文字的範疇,描述文本的顔色、大小、字型。

HTML由一個個标簽組成,标簽各司其職,有的提供網頁資訊,有的負責圖檔,有的負責網頁布局。

超文本需要顯示,就得有軟體呈現超文本定義的排版格式,,例如顯示圖檔、表格、顯示字型的大小,顔色,軟體就是浏覽器。

超文本的誕生是為了解決純文字不能格式顯示問題,是為了好看,但是隻用通過網絡分享超文本的内容,是以制定了HTTP協定。

2、浏覽器

1)曆史、1980年代,tim berners-Lee為cern設計基于超文本思想的enquire,以促進科研人員之間資訊更新和共享。19899年其編寫了《資訊化管理;建議》一文,并建構基于Internet的hypertext系統,并在cern開發了world wide web項目。打造了世界上第一站。于1991年8月6日上線。

Tim berners-lee于1990年發明了第一個浏覽器,還發明了HTTP協定。

1994年MIT建立了w3c。w3c網際網路聯盟,負責網際網路持續發展,提出w3c的标準應該基于無專利權、無版稅。

Marc Andreessen于1993年發明了mosaic浏覽器,看到了技術前景,不久後成立自己的公司---網景公司Netscape,1994發不了Netscape navigator浏覽器,席卷全球。

1995年微軟釋出IE。

1999年網景被aol收購,收購後,Netscape公開了浏覽器代碼。建立了Mozilla組織。Mozilla組織使用gecko引擎重寫浏覽器。。

2003網景被解散。

2008年google的Chrome浏覽器待着v8引擎橫空出世。

2)網景公司

HTTP cookie,解決HTTP無狀态。

Javascript

Ssl協定:

Jar格式檔案,将Java的class檔案打包壓縮,并加上簽名。

2012年4月9日,微軟購買800項美國線上的專利或專利授權。

3)浏覽器技術

浏覽器是特殊的用戶端。

浏覽器軟體分為兩個部分

         外殼:

         外殼提供使用者互動的界面。

         核心(引擎engine)

         提供HTML,css,圖像的渲染引擎。提供DOM程式設計接口。

         提供Javascript引擎。

排版(渲染)引擎 浏覽器 說明
Gecko Firefox
Trident IE,AOL
Khtml
Presto oPera
Webkit Safari,Chrome
Blink Chrome,Opera

Js引擎:

Jscript、tracemonkey(firefox)  v8等

使用jquery等架構來解決相容性問題。

3、js

是一種動态的弱類型的腳本解釋性語言。和HTML、css秉承三大web核心技術。

4、ES

ECMAscript:是ecma國際組織

JavaScript是商品名。

2009年 ES5釋出

2015年ES6釋出

5、v8引擎

谷歌推出的,使用的是bsd協定開源。

二、nodejs

1、nodejs簡介

Nodejs是伺服器端運作JavaScript的開源、跨平台運作環境。

作者是瑞安達爾(ryan dahl),2009年釋出,使用了v8引擎,采用時間驅動,非阻塞,異步IO模型。

2012年,npm軟體包管理器誕生,通過其,可以友善的釋出,分享nodejs的庫和源代碼。

Nodejs4.0引入了ES6語言的特性。

2、安裝

國内阿裡雲鏡像

https://npm.taobao.org/mirrors/node

Linux:

https://npm.taobao.org/mirrors/node/latest-v8.x/node-v8.11.3-linux-x64.tar.xz

windows:

https://npm.taobao.org/mirrors/node/latest-v8.x/node-v8.11.3-x64.msi

預設路徑安裝:

3、開發

Visual studio code

https://code.visualstudio.com/Download

4、注釋

和c、Java一樣

//單行注釋

/*comment*/ 

多行注釋,在語句中間使用。

str = \'hello\' + /*comment*/ \'student\'

5、常量和變量

辨別符

辨別符必須是字母、下劃線、美元符号和數字,但必須是字母、下劃線、美元符号開頭。,不能是數字開頭。

辨別符區分大小寫。

聲明

var 

a聲明   a值為undefined   聲明全局變量

let 

b 聲明   let  塊變量,局部變量。

const 

c常量聲明時候必須指派。後期不允許更改。明确知道一個辨別符定以後不在膝蓋,聲明的時候使用const常量,減少被修改的風險。

能給常量就不用變量。

變量和常量聲明和初始化的過程中是可以分開的。

var a

let b

console.log(a,b)

a = 1

b = \'a string\'

console.log(a,b)

//const c   //不能定義,因為const定義時候必須指派,之後不可以再次進行更改

const c = 100

console.log(c)

var y //隻是複制,y的值為undefined

var x = 1 //規範的聲明并初始化,聲明全局或局部變量

function hello()

{

    var a    //隻是聲明,a為undefined,作用域是在函數中

    a = 100   //指派 

}

//console.log(2,a)   //抛出錯誤,變量a未定義

//a = 200   //不能提升作用域

//var a = 200;hello();   //var提升作用域

//console.log(3,a)

6、資料類型

序号 名稱 說明
1 number 數值型
2 boolean 布爾型,true和False
3 String 字元串
4 Null 隻有一個null值
5 Undefined 變量聲明未指派的
6 Symbol Es6新引入的類型
7 object類型 以上基本類型的複合類型,容器

ES是動态弱語言,弱類型語言,雖然先聲明了變量,但是變量可以重新指派任何類型。

//string

console.log(\'----string-------\')

console.log(a = 3+\'abc\',typeof(a))

console.log(a = null + \'abc\',typeof(a))

console.log(a = undefined + \'abc\',typeof(a))

console.log(a = true + \'abc\',typeof(a))

//number

console.log(\'----number----\')

console.log(a = null + 1,typeof(a))

console.log(a = undefined + 1,typeof(a))   //undefined沒有辦法轉成對應的數字,隻是顯示男,not a number

console.log(a = true + 8,typeof(a))

console.log(a = false + 8,typeof(a))

//boolean

console.log(\'----bool----\')

console.log(a = null + true,typeof(a))

console.log(a = null + false,typeof(a))

console.log(a = undefined + true,typeof(a))   //undefined沒有辦法轉成對應的數字

console.log(a = undefined + false,typeof(a))  //undefined,不能轉成對應的數字

console.log(a = null & true,typeof(a))

console.log(a = undefined & true,typeof(a))

//短路

console.log(a = null && true,typeof(a))

console.log(a = false && null,typeof(a))

console.log(a = false && \'abc\',typeof(a))

console.log(a = true && \'abc\',typeof(a))

console.log(a = true && \'\',typeof(a))

//null

console.log(a = null + undefined,typeof(a))

----string-------

3abc string

nullabc string

undefinedabc string

trueabc string

----number----

1 \'number\'

NaN \'number\'

9 \'number\'

8 \'number\'

----bool----

1 \'number\'

0 \'number\'

NaN \'number\'

NaN \'number\'

0 \'number\'

0 \'number\'

null \'object\'

false \'boolean\'

false \'boolean\'

abc string

 string

NaN \'number\'

類型運算:

String:與str相加全部轉化為str類型。

Number:與number相加全部轉化為number

Boolean類型:轉為話number類型

弱類型,不需要強制類型轉換,會隐士的類型轉換。

總結:

遇到字元串,加号就是拼接字元串。

如果沒有遇到字元串,加号就是把其他的所有的類型都當做數字處理。

Undefined特殊,因為他沒有定義值,是以是一個特殊的數字nan.

如果運算符是邏輯運算符,短路符,傳回的就是短路時候的類型,沒有隐士轉換,

盡量使用顯示的轉換。

7、字元串

将一個值利用單引号或者雙引号引起來就是字元串。

Es6提供了反引号定義一個字元串,可以支援多行,還可以支援插值。

字元串:插值。使用反引号$符号進行插值,指派即定義。

let a = \'abc\'

let b = \'ced\'

let c = `line1

line2

line3

`

console.log(c)

let name = \'tom\',age = 19

console.log(`hi name is ${name},age${age}`)

line1

line2

line3

hi name is tom,age19

8、轉義字元

名稱 說明
\0 Null位元組
\b 倒退符
\f 換頁符
\n 換行符
\r 回車符
\t Tab制表符
\v 垂直制表符
\’ 單引号
\” 雙引号
\ 反斜杠符(\)
\XXX 由從0到377最多三位八進制數XXX,例如\251是版權符号的八進制序列
\xXX 由從00和FF的兩位十六進制數字XX表示的Latin-1字元。\ x A9是版權符号的十六進制序列
\uXXXX 由思維十六進制數字XXXX的Unicode字元,例如,\u 00A9是版權符号的Unicode序列。見Unicode escape sequences(Unicode轉義字元)
\u{XXXXX} Unicode代碼點(code point)轉義字元,例如\u{2F804}相當于Unicode轉義字元\uD87E\uDc04的簡寫。

9、字元串操作方法

let a = \'abcdefgh\'

console.log(a.charAt(2))    //索引查找字元串

console.log(a[2])        //索引查找字元串

console.log(a.toUpperCase())  // 大寫

console.log(a.concat(\'.com\'))  

//拼接字元串

console.log(a.slice(3))     

//  切片

console.log(a.slice(3,6))    //

console.log(a.slice(-2,-1))   //負索引切片

console.log(a.slice(-2))    //負索引切片

c

c

ABCDEFGH

abcdefgh.com

defgh

def

g

gh

let url = \'www.google.com\'

console.log(url.split(\'.\'))   //以什麼進行切割

console.log(url.substr(7,2))   //

傳回字元串從何處開始,取多長

console.log(url.substring(7,10)) 

// 傳回子串,從何處開始,到什麼為止

[ \'www\', \'google\', \'com\' ]

gl

gle

let url1 = \'www.google.com\'

console.log(url1.indexOf(\'com\'))     

//   查找字元串所在的索引

console.log(url1.replace(\'.com\',\'.cn\'))   //替換

console.log(url1.indexOf(\'gle\',3))   

//   向右偏移3

url2 = \'\tmg edu \r\n\'

console.log(url2.trim())       //去除兩端的空白字元串

11

www.google.cn

7

mg edu

10、數值型number

在js中,資料均為雙精度浮點型範圍隻能在- +(2^53-1)之間,整型不例外。

數字類型還有三種符号值:+infinity(正無窮)  -infinity(負無窮)和nan(not-a-number非數字)  

二進制0b。

八進制0o   

十六進制0x

指數表示1E3(1000),2e-2(0.02)

常量屬性:

數字的方法;

方法 描述
Number.parseFloat() 把字元串參數解析成浮點數,和全局方法parseFloat()作用一緻
Number.parseInt() 把字元串解析成特定基數對應的整型數字,和全局方法parseInt()作用一緻
Number.isFinite() 判斷傳遞的值是否為有限的數字
Number.isInteger() 判斷傳遞的值是否為整數
Number.isNaN() 判斷傳遞的值是否為NaN

内置數學對象:Math

有絕對值,對數、指數運算、三角函數運算、最大值、最小值、随機數、開方等運算函數。

console.log(Math.PI)    //3.14 PI值

console.log(Math.abs(-1))   //絕對值

console.log(Math.log2(16))   // 開方

console.log(Math.sqrt(2))    //平方根

console.log(Math.random())    //随機數

11、運算符

1)算數運算符

+ - * / %

console.log(1/2)   //0.5

console.log(1/0)  //Infinity

console.log(5%3)   //2

console.log(parseInt(1/2))     // 

0  向下取整

console.log(parseInt(3/2))     // 1  

向下取整

console.log(Math.floor(3/2))   // 1  

向下取整

console.log(Math.ceil(3/2))    // 2  

向下取整

console.log(Math.round(3/2))   // 

2  四舍五入

console.log(Math.round(1/2))   // 

1  四舍五入

++和—

單目運算符,表示變量自增,自減

I++ 先用i,用完之後在加1

++I i先自增,在使用i

let i = 0

let a = i++

console.log(a,i)   //0  

1

console.log(a,i++)   // 0  

1

a = ++ i

console.log(a,i)    // 3 

3

單目運算符是優先級高于雙目運算符。

 7

i = 0;

let a = ++i+i+++i+++i; //++i + i++ i++ +i

console.log(a);        //  1  

1   2    3  7

2)比較運算符

不做隐士的類型轉換寫的是===。

不做兩個等等号。嚴格相等使用三個等号。

console.log(100  > \'200\') //  false

console.log(100 > \'a\')   //false

console.log(300 == \'300\')  //true

console.log(300 === \'300\')  //false

3)邏輯運算符

&&,||,!  與或非

4)位運算

& | 

^ ~<< >>位與,位或,異或,取反,左移,右移。

5)三元運算符

條件表達式?真值:假值

console.log((\'3\' > 30)?\'真\':\'假\')

6)逗号操作符

Js運作多個表達式寫在一起

let a = 4+5,b = true,c=a > 20?\'t\':\'f\'

console.log(a)   // 9

console.log(c)    // f

7)其他

名稱 說明
Instanceof 判斷是否屬于指定類型
Typeof 判斷類型字元串
Delete Delete操作符,删除對象
In  判斷指定的屬性在對象内,則傳回true

console.log(\'a\' instanceof String) 

// false

console.log(1 instanceof Number)   

// false

a = new String(\'b\')                

console.log(a instanceof String) 

// true

console.log(new Number(1) instanceof Number) // true

console.log(a instanceof Object) // true

Instance必須明确使用的類型定義變量。沒有 new方法的類型的都不是初始的類型。可以用于繼承關系的判斷。

Typeof就是傳回對象的類型字元串。

Delete删除對象、屬性、數組元素

8)運算符優先級

運算符由高到低。

var trees = new Array();

逗号運算符優先級最低,比指派語句還低。

9)表達式(生産器)

function* inc()

{

    let i = 0;

    let j = 2;

    while(true){

        yield i++

        if (!j--)return  100;

    }

}

let gen = inc()

for (let i = 0 ;i<10;i++)

console.log(gen.next());

{ value: 0, done: false }

{ value: 1, done: false }

{ value: 2, done: false }

{ value: 100, done: true }

{ value: undefined, done: true }

{ value: undefined, done: true }

{ value: undefined, done: true }

{ value: undefined, done: true }

{ value: undefined, done: true }

{ value: undefined, done: true }

每次調用next()方法傳回一個對象,這個對象包含兩個屬性:value和done,value屬性表示本次yield表達式的傳回值,done屬性為布爾值,done是False表示後續還有yield語句執行,如果執行完成或者return後,done為true。

三、js文法

1、語句塊

function hello(){

    let a = 1;

    var b = 2;

    c =3

}

if (1)

{

    let d = 4;

    var e = 5;

    f = 6

    if (true){

        console.log(d)

        console.log(e)

        console.log(f)

        console.log(\'------\')

        g = 10

        var h = 11

    }

}

console.log(e)

console.log(f)

console.log(g)

console.log(h)

4

5

6

------

5

6

10

11

大括号中都是一個作用域。

Let定義的外部不能通路,隻能是内部才能通路。Var塊作用域,外部可以見到,普通定義外部也可見。

2、條件分支

if (cond1){

}

else if(cond2){

}

else if (cond3){

}

else{

}

條件False等效

 False

Undefined

Null

NaN

空字元串(””)

3、switch..case分支語句

switch (expression){

    case label_1

statements_1

        [break;]

    case label_2

statements_2

        [break;]

    default:

statements_def

        [break;]

}

let x = 5

switch (x){

    case 0:

        console.log(\'zero\')

        break;

    case 1:

        console.log(\'one\')

    case 2:

        console.log(\'two\')

    case 3:

        console.log(\'three\')

        break;

    case 4:

        console.log(\'four\')

    default:

        console.log(\'other\')

        break;

}

Switch…case語句都可以協程多分支結構。

4、for循環

//for ([initialExpression];[condition];[increamentExpression])

//{

  //  statement

//}

for (let i=0;i<10;i++){

    console.log(i)

}

console.log(\'---\')

5、while循環和do….while循環

While (condition)

         Statement

條件滿足,進入循環,條件為真,繼續循環

do

         statement

while (condition);

先進入循環,然後判斷,為真就繼續循環。

let x = 10;

while(x--){

console.log(x);

}

do{

console.log(x);

}while(x++<10)

列印九九乘法表:

for (let x =

1;x<10;x++)

{   

    line = \'\';

    for(let y = 1;y<=x;y++)

        line += `${x}*${y}=${x*y}`;

console.log(line)

}

5、for…in 循環

對象操作語句for…in用來周遊對象的屬性

for (variable in object){

statements}

let arr =[10,20,30,40 ]

console.log(arr[2])  

//30

for (let x in arr)

  console.log(x)

for (let index in arr)

console.log(`${index}:${arr[index]}`);

for (let i=0;i<arr.length;i++)

console.log(arr[i]);

let obj = {

  a:1,

  b:\'abc\',

  c:true

};

console.log(obj.a)

console.log(obj[\'b\'])

console.log(obj.d)

console.log(\'++++++\')

for (let x in obj)

console.log(x) 

//屬性名

for (let key in obj) 

//傳回數組的index

console.log(`${key}:${obj[key]}`);

30

1

2

3

0:10

1:20

2:30

3:40

10

20

30

40

1

abc

undefined

++++++

a

b

c

a:1

b:abc

c:true

for in 循環傳回的是索引或者key,需要簡介通路到值。

數組反正傳回的是索引,c風格for循環操作簡單。

6、for..of循環

Es6的新文法

let arr =

[1,2,3,4,5]

let obj = {

  a;1,

  b:\'abc\',

  c:true

}

for (let i of

arr){  //傳回數組的元素

  console.log(i)

}

for (let i of

obj){  //異常,不可以疊代

  console.log(i)

}

For….of不能是疊代對象。

原因是of後面必須是一個疊代器(typeerror)

break 、continue

break結束目前循環

continue中斷目前煦暖,直接進入下一次循環。

7、for疊代的差别

function sum(arr){

  for (let x in arr){

    console.log(x,typeof(x),arr[x]);

  }

  for (let x of arr){

    console.log(x,typeof(x));

  }

  for (let x =

0;x<arr.length;x++){

console.log(x,typeof(x),arr[x])

  }

}

X退出的時候還是會加一或減一。

四、函數及作用域

1、函數表達式

function //函數名(參數清單){

    //函數體;

    return //傳回值;

}

function add(x,y){

    return x + y

}

console.log(add(3,5))

匿名函數表達式

const add = function(x,y){

    return x + y;

};

console.log(add(4,5))

有名字的函數表達式

const add1 = function fn(x,y){

    return x + y;

};

console.log(add1(3,4))

有名字的函數表達式,名字隻能内部使用,外部不可見

const add2 = function _add(n){

    if (n === 1) return n;

    return n+ _add(--n)

};

console.log(add2(5))

函數、匿名函數、函數表達式的差異

函數和匿名函數,本質上是一樣的,都是函數對象,不過函數都有自己的辨別符,函數名,匿名函數需要的是借助其他的辨別符而已。

差別在于,函數會聲明提升,函數表達式不會。

console.log(add(3,4))

function add(x,y){     //聲明提升

    return x + y;

};

console.log(sub(4,5))   //會報出異常的,提示sub未定義

const sub = function(x,y){

    return x + y;

};

定義函數的形式:function表達式。(有名字和匿名的),有名字的内部使用等。

聲明先做,調用後做。

生成器:

const counter = (function *(){

    count = 1

    while(1)

        yield count ++;

})();

console.log(counter.next())

2、高階函數

高階函數:函數作為參數或者傳回一個函數。

const counter = function(){

    let c = 0;

    return function(){

        return c++

    };

};

const c = counter()

console.log(c())

console.log(c())

map函數的實作

const map = function(arr,fn){

    newarr = []

    for (i in arr){

        newarr[i] = fn(arr[i])

    }

    return newarr

};

console.log(map([1,2,3,4],function(x){

    return ++x

}));

3、箭頭函數

const map1 = function(arr,fn){

    newarr = []

    for (i in arr){

        newarr[i] = fn(arr[i])

    }

    return newarr

}

console.log(map([1,2,3,4],x =>++x))

// console.log(map1([1,2,3,4],x =>++x))

// console.log(map1([1,2,3,4],x=>{return ++x}))

console.log(map1([1,2,3,4],(x)=>{return ++x}))

箭頭函數就是匿名函數定義。 

去掉關鍵字function。

一個參數的時候可以省掉括号。無參和多參數的時候必須保留括号。多個參數使用逗号分隔。

有大括号的時候必須有return。

定義是定義的形式。調用必須加括号,因為有優先級的問題,是以調用前面的利用括号抱起來。

箭頭函數的傳回值:

如果函數體部分有多行,就需要使用{},如果有傳回值使用關鍵字return。

如果隻有一行語句,可以同時省略大括号和return。

隻要有return語句,就不能省略大括号,有return必須有大括号。

隻有一條非return語句,加上大括号,函數就是沒有傳回值了。

Map函數:

function map(arr,fn){

    newarr1 = []

    for (i in arr)

        newarr1[i] = fn(arr[i])

    return newarr1

};  

console.log(map([1,2,3,4],function(x){

    return ++x;

}));

4、參數

傳參是按照位置對應的,沒有關鍵字傳參這個屬性。寫的像的話隻是指派語句。

傳參的是隻是表達式的值。

數組不解構的話當做一個來進行,解構利用…

預設值可以進行定義的。位置傳參的,預設值往後寫

//位置傳參

const add = (x,y)=> x+y;

console.log(add(4,5));

//預設值

const add1 = (x,y=6)=>x+y;

console.log(add1(4))

//非關鍵字傳參,沒有關鍵字傳參,隻是表達式

const add2 = (x,y)=>x+y;

console.log(add2(z=1,c=2))

//預設值不能放在前,否則就是轉換為3和undefined相加,加過為NaN

const add3 = (x=1,y)=>x+y;

console.log(add3(3))    //NaN

5、可變參數

(1)args

const sum = function(...args){

    let resule = 0;

    for (i in args){

        resule += args[i]

    };

    return resule

};

console.log(sum(2,3,4))

可變參數使用…args.

(2)arguments對象

const sum = function(...args){

    let resule = 0;

    console.log(arguments)

    for (i in args){

        resule += args[i]

    };

    return resule

};

console.log(sum(2,3,4))

{ \'0\': 2, \'1\': 3, \'2\': 4 }

所有的參數會儲存到一個k,v,鍵值對的字典裡面。

(3)參數解構

const add = function (x,y){

    return x+y

}

console.log(add(...[100,200,300,400,500]))   //參數解構,不需要參數一一對應的。

參數解構,不需要和需要的參數一一對應。

6、傳回值

Return的傳回值:傳回的通常是幾個參數,傳回的是最後一個參數的值。逗号表達式的。

const add1 = (x,y)=>{return x,y}

console.log(add1(1,2))

表達式的值:

逗号表達式,最後一個的值。

傳回 的都隻是一個單值。

a = (x = 5,y=6,true);

console.log(a)

b = (x=1,y=4,\'abc\');

console.log(b)

function c() {

    return x= 1,y=2,\'abc\',false;

}

console.log(c());

7、作用域

Function函數定義,是獨立的作用域,内部定義的變量外部不可以見到。

//函數作用域

function c(){

    a = 1

    var b = 2

    let c1 = 3

};

c();

console.log(a)

//console.log(b)   //  函數中var定義變量沒有方法突破,外界見不到

//console.log(c1)  //   let定義的外界見不到

//塊作用域

if (1){

    d = 4

    var e = 5

    let f = 6

}

console.log(d)

console.log(e)       //var 塊中定義的才會外界可以見到。

// console.log(f)      //let定義外界始終見不到

var b = 2可以提升聲明,可以突破非函數的塊作用域。

a = 1 隐士聲明不能進行提升聲明,

let a=3不能提升聲明。

嚴格模式:使用”use strict”語句放到函數的首行,或者js腳本首行。

function show(i,args){

    console.log(i,args)

};

x = 100;

function fn(){

    let z = 200;

    {

        var a = 300;

        show(1,x)

        t = \'free\'

        let p = 400;   

    }

    var y = 500

    show(2,z)

    show(3,x)

    show(4,a)

    show(5,t)

    //show(5.5,p) //異常,let出不來上一個語句塊

    {

        show(6,y);

        show(7,a)

        show(8,t)

        {

            show(9,a)

            show(10,t)

            show(11,z)

        }

    }

}

fn()

 // show(12,y)   //異常,出不了函數的y

show(13,t)

 // show(14,a)   //異常,a不能出函數的

show(15,z)  

//變量聲明提升,聲明了z,但是還沒指派

var z = 10;

五、js對象模型

基于原型的面向對象語言,而不是基于類的面向對象語言。

基于對象事件。

Js是基于原型的語言,隻有原型對象的概念,原型對象就是一個模闆,新的對象從這個對象模闆建構進而擷取最初的屬性,任何對象在運作時候可以動态的增加屬性。任何一個對象都可以作為另一個對象的原型,後者就可以共享前者的屬性。

1、定義類

var obj = {

}

var obj1 = new Object();

var obj2 = new Object;

建立的時候必須使用new方法。

function定義的時候 大駝峰。

字面聲明方式。

2、es6之前---構造器

function Point(x,y){

    this.x = x

    this.y = y

    this.show = ()=>console.log(1,this,this.x,this.y)

};

console.log(Point)

p1 = new Point(4,5)

console.log(2,p1)

function Point3D(x,y,z){

    Point.call(this,x,y);

    this.z = z

    console.log(3,\'Point 3d\')

};

console.log(4,Point3D)

p2 = new Point3D(3,4,5)

console.log(5,p2)

p2.show();

[Function: Point]

2 Point { x: 4, y: 5, show: [Function] }

4 [Function: Point3D]

3 \'Point 3d\'

5 Point3D { x: 3, y: 4, show: [Function], z: 5 }

1 Point3D { x: 3, y: 4, show: [Function], z: 5 } 3 4

(1)定義一個函數(構造器)對象,函數名首字母大寫。

(2)This指代是目前執行個體的本身。定義屬性。

(3)使用new和構造器建立一個通用對象。New操作符會将新的對象的this值傳遞給point3d構造器函數,函數為這個對象建立z屬性。

如果不使用new方法,就是普通的函數調用,this不代表執行個體。

3、es6中的class

(1)class

Es6開始,提供了關鍵字class,建立對象更加簡單、清晰。

(1)利用關鍵字class,建立的本質上還是一個函數,是特殊的函數。

(2)一個類隻能擁有一個名為constructor的構造器方法,如果沒有顯示定義一個構造方法,,就會預設添加一個constructor方法。

(3)繼承使用extends關鍵字

(4)一個構造器可以使用super關鍵字來調用父類的構造函數。

(5)類沒有私有屬性。

class Point{

    constructor(x,y){

        this.x = x

        this.y = y

    }

    show(){

        console.log(this,this.x,this.y)

    }

}

let p1 = new Point(10,11)

p1.show()

class Point3D extends Point{

    constructor(x,y,z){

        super(x,y);

        this.z = z

    }

}

let p2 = new Point3D(4,5,6)

p2.show()

Point { x: 10, y: 11 } 10 11

Point3D { x: 4, y: 5, z: 6 } 4 5

重新寫show方法;

class Point{

    constructor(x,y){

        this.x = x

        this.y = y

    }

    show(){

        console.log(this,this.x,this.y)

    }

}

p1 = new Point(1,2)

console.log(p1)

class Point3D extends Point{

    constructor(x,y,z){

        super(x,y)

        this.z= z

    }

    show(){

        console.log(this ,this.x,this.y,this.z)

    }

}

p2 = new Point3D(3,4,5)

console.log(p2)

子類中直接重寫父類的方法即可,如果需要使用父類的方法,使用super.method()的方式調用。

使用箭頭函數修改:

class Point{

    constructor(x,y){

        this.x = x

        this.y = y

        this.show = ()=>console.log(\'point\')

    }

}

//繼承關系

class Point3D extends Point{

    constructor (x,y,z){

        super(x,y,z)

        this.z = z

        this.show=()=>console.log(\'point3d\')

    }

}

let p2 = new Point3D(3,4,5);

p2.show()

point3d

子類覆寫,最終顯示的結果是point

class Point{

    constructor(x,y){

        this.x = x

        this.y = y

        this.show =()=>

            console.log(\'point\')

    }

}

class Point3D extends Point{

    constructor(x,y,z){

        super(x,y)

        this.z = z

        //this.show=()=>console.log(\'Point3d\')   

    }

     show(){

        console.log(\'point3d\')

     }

}

優先使用執行個體的方法,show方法,使用this的方法。

class Point{

    constructor(x,y){

        this.x = x

        this.y = y

        //this.show =()=>

          //  console.log(\'point\')

    }

    show(){

        console.log(this,this.x,this.y)

    }

}

class Point3D extends Point{

    constructor(x,y,z){

        super(x,y)

        this.z = z

        this.show=()=>console.log(\'Point3d\')   

    }

     //show(){

       // console.log(\'point3d\')

     //}

}

let p1 = new Point3D(2,3,4)

console.log(p1)

p1.show()

屬性優先,一定先用屬性。優先使用子類的屬性。

總結:如果子類和父類使用同一種方式進行定義,子類覆寫父類的。

如果父類使用的屬性,子類使用的是方法,那麼就是采用父類的屬性。

如果子類使用的屬性,父類是方法,那麼優先使用的是子類的屬性方法。。

最終總結,屬性優先。。同一類定義的,子類優先

靜态屬性:

靜态方法沒有很好的支援的。

(2)靜态方法:

在方法名前面加上static,就是靜态方法了。

class Add{

    constructor(x,y){

        this.x = x

        this.y = y

    }

    static show(){

        console.log(this.x)  //this是Add   不是Add的執行個體

    }

}

a = new Add(2,3)

console.log(a)

 //a.show()    執行個體不能直接通路靜态方法

a.constructor.show()  //執行個體可以通過constructor構造器方法通路靜态方法。

靜态方法總結:執行個體不能直接通路靜态方法,執行個體必須通過constructor方法通路靜态方法。

靜态成員必須使用類來定義的。

執行個體是自己的。

4、this的坑

var shcool = {

    name : \'abc\',

    getNameFunc: function(){

        console.log(1,this.name)

        console.log(2,this)

        return function(){

            console.log(3,this === global);

            return this.name

        }

    }

};

console.log(4,shcool.getNameFunc()());

this是全局的global的,是以第三行是true。

第四行,This是global的,所喲下面的return this.name沒有name屬性。

函數調用的時候調用的方式不用,this的對象就是不同的。

函數執行的時候,會開啟新的執行上下文環境executioncontext。

建立this屬性。

(1)myfunction(1,2,3)普通的函數調用,this指向的是全局對象,全局對象是nodejs的global或者浏覽器的window。

(2)myObject.myFunction(1,2,3),對象的方法調用方式,this指向包含該方法的對象。

(3)call和apply方法的調用,都要看第一個參數是誰。

解決this的問題。

1)顯式傳入

var shcool1 = {

    name : \'cde\',

    getNameFunc1 : function(){

        console.log(this.name)

        console.log(this);

        return function(that){

            console.log(this === global);

            return that.name;

        }

    }

}

console.log(shcool1.getNameFunc1()(shcool1))

cde

{ name: \'cde\', getNameFunc1: [Function: getNameFunc1] }

true

cde

利用關鍵字that   傳入對象。主動傳入對象,避開了this的問題

2)引入call、apply方法。

var shcool2 = {

    name : \'asd\',

    getNameFunc2:function(){

        console.log(this.name)

        console.log(this);

        return function(){

            console.log(this === global);

            return this.name

        }

    }

}

console.log(shcool2.getNameFunc2().call(shcool2));

asd

{ name: \'asd\', getNameFunc2: [Function: getNameFunc2] }

false

asd

call方法和apply都是函數對象的方法,第一參數都是傳入對象引入的。

Apply傳其他參數需要數組。

Call傳其他參數需要使用可變參數收集。

3)bind方法

var school3 = {

    name: \'asdd\',

    getNameFunc3:function(){

        console.log(1,this.name)

        console.log(2,this)

        return function(){

            console.log(3,this === global);

            return this.name;

        }

    }

};

// console.log(school3.getNameFunc3().bind(school3));

var func = school3.getNameFunc3()

console.log(4,func)

var bindfunc = func.bind(school3)

console.log(5,bindfunc)

console.log(6,bindfunc())

1 \'asdd\'

2 { name: \'asdd\', getNameFunc3: [Function: getNameFunc3] }

4 [Function]

5 [Function: bound ]

3 false

6 \'asdd\'

Apply、call方法,參數不同,調用時候傳入this。

。bind方法是為函數綁定this,調用時候直接調用

4)es6引入的箭頭函數定義

var school = {

    name :\'ass\',

    getNameFunc:function(){

        console.log(this)

        console.log(this.name)

        return ()=>{

            console.log(this === global);

            return this.name

        }

    }

};

console.log(school.getNameFunc()())

{ name: \'ass\', getNameFunc: [Function: getNameFunc] }

ass

false

ass

class school{

    constructor(){

        this.name = \'abcd\';

    }

    getNameFunc(){

        console.log(this.name)

        console.log(this);

        return ()=>{

            console.log(this === global);

            return this.name

        }

    }

};

console.log(new school().getNameFunc()())

abcd

school { name: \'abcd\' }

false

abcd

綁定之後傳回一個新的函數。

全局對象。

全局global,

浏覽器中叫做window

解決this文法的利用bind。

5、高階對象、高階類、或稱為Mixin模式

Mixin,混合模式,不用繼承就可以複用的技術,主要還是為了解決多重繼承的問題,多繼承的路徑是個大問題。

Js是基于對象的,類和對象都是對象模闆。

混合Mixin,指的四将一個對象的全部或者部分拷貝到另一個對象上去,其實就是屬性了。

可以将多個類或對象混合成一個類對象。

指的是将一個對象的全部或者部分拷貝到另一個對象上去。

傳回的是定義的類。

class Serialization{

    constructor(){

        console.log(\'serialization construtor---\');

        if (typeof(this.stringify) !== \'function\'){

            throw new ReferenceError(\'should define stringify\')

        }

    }

}

class Point extends Serialization{

    constructor(x,y){

        console.log(\'Point constructor\');

        super()

        this.x = x

        this.y = y

    }

    stringify(){

        return 

`<point x=${this.x},y=${this.y}>`

    }

}

class Point3d extends Point{

    constructor(x,y,z){

        super(x,y);

        this.z = z

    }

    stringify(){

        return `<point x=${this.x},y=${this.y},z=${this.z}>`

    }

}

p = new Point(4,5)

console.log(p.stringify())

p3d = new Point3d(7,8,9)

console.log(p3d.stringify())

Point constructor

serialization construtor---

<point x=4,y=5>

Point constructor

serialization construtor---

<point x=7,y=8,z=9>

高階對象實作,将類的繼承建構成為箭頭函數

//普通繼承

class A extends Object{};

console.log(A)

//匿名類

const A1 = class{

    constructor(x){

        this.x = x;  

    }

}

console.log(A1)

console.log(new A1(100).x)

//匿名繼承

const B = class extends Object{

    constructor(){

        super()

        console.log(\'B constorse\')

    }

};

console.log(B)

b = new B()

console.log(b)

[Function: A]

[Function: A1]

100

[Function: B]

B constorse

B {}

Point3d調用父類serialization,此類然後調用繼承point類。

盡量少的改變原有代碼的方式增強注入函數的功能。Extends繼承,就是Mixin類,混入的類型。

React架構大量使用了Mixin類。

const x = (Sup) =>{

    return class extends Sup{

        constructor(){

            super();

            console.log(\'c constructor\')

        }

    }

};

const c = Sup =>class extends Sup{

    constructor(){

        super();

        console.log(\'c constorce\')

    }

};

cls = c(A)

console.log(cls)

a = new cls();

console.log(a);

const Serialization = Sup => class extends Sup{

    constructor(...args){

        console.log(\'serialization constructor--\')

        super(...args);

        if (typeof(this.stringify)!==\'function\'){

            throw new ReferenceError(\'should define stringify\')

        }

    }

}

class Point{

    constructor(x,y){

        console.log(\'point constrouct\')

        this.x =x

        this.y =y

    }

}

class Point3d extends Serialization(Point){

    constructor(x,y,z){

            super(x,y)

            this.x = x

        }

    stringify(){

        return `<point3d ${this.x}.${this.y}>`

    }

}

let p3d = new Point3d(1,2,3)

console.log(p3d.stringify())

serialization constructor--

point constrouct

<point3d 1.2>

Serialization(point)實際上是匿名函數的調用,傳回一個新的類型,point3d繼承來自這個新的匿名函數類型,增強了功能。

React架構大量使用了Mixin技術。

六、異常

1、抛出異常

使用throw關鍵字抛出異常。

使用throw關鍵字可以抛出任意對象的異常

2、捕獲

try…catch語句捕獲異常

try….catch…finally ,語句捕獲異常,finally保證最終一定執行。

try{

    throw 1;

}catch (error){

    console.log(error.constructor.name);

}finally{

    console.log(\'end\')

}

3、子產品化

(1)簡介

Js主要是在前端的浏覽器中使用,js檔案下載下傳緩存到用戶端,在浏覽器中執行。

簡單的表單的本地驗證,漂浮廣告。

伺服器端使用ASP、JSP等動态網頁技術,将東外生成資料嵌入一個HTML模闆中,裡面夾雜着js後使用<script>标簽,傳回給浏覽器端。Js隻是簡單的函數和語句的組合。

2005年後,google大量使用ajax技術,可以一步請求伺服器端資料,前端互動的巨大變化,

前端功能需要越來越多,代碼多,js檔案的增多。全局變量污染,函數名沖突,無法表達腳本之間的依賴關系,用腳本檔案先後加載實作的,需要子產品化的出現。

2008年v8引擎,2009年nodejs,支援伺服器端JS程式設計,沒有子產品化是不可以的。

之後産生了commonjs規範,

Common規範,使用全局 require函數導入子產品,使用exports導出變量。

AMD(asynchronous module

definition)異步子產品定義:使用異步方式加載子產品,子產品的加載不影響他後面語句的執行,所有依賴此子產品的語句,都需要定義在一個回調函數裡面,回調函數中使用子產品的變量和函數,子產品加載完成後,回調函數才會執行,就可以安全的使用子產品的資源,就是AMD/requires。AMD雖然是異步,但是會預先加載和執行。

CMD(common module definition),使用seajs,作者是淘寶前端玉伯,相容并包解決了requirejs的問題。Cmd推崇as lazy as possible,盡可能的懶加載。

(2)ES6子產品化

Import語句,導入另一個子產品導出的綁定。

Export語句,從子產品中導入函數、對象、值,供其他子產品import導入引用。

(3)導出

建立子產品的目錄src,此目錄下建立mode.js,  内容是導入和導入子產品的代買

export default function a(){   //導出預設的

    console.log(\'a is t1\')

};

a();

//導出函數

Export function foo(){

    Console.log(‘foo function’);

}

//導出常量

Export const consta = ‘aaa’

(4)導入

import a from \'./t1-1\'

a();

vs code可以很好的文法支援,但是運作環境和v8引擎,不能很好的支援子產品化文法。

4、編譯器

轉譯從一種語言代碼轉換到另一語言代碼,當然也可以從高版本轉譯到低版本的支援語句。

由于js存在不同的版本,不同浏覽器相容問題,使用transpiler轉譯工具解決。

Babel

開發中比較新的es6的文法,通過轉移器指定Wie特定的某些版本代碼。

官網:http://babeljs.io/

function* inc()

{

    let i = 0;

    let j = 2;

    while(true){

        yield i++

        if (!j--)return  100;

    }

}

let gen = inc()

for (let i = 0 ;i<10;i++)

console.log(gen.next());

轉化結果:

"use strict";

var _marked = /*#__PURE__*/regeneratorRuntime.mark(inc);

function inc() {

    var i, j;

    return regeneratorRuntime.wrap(function

inc$(_context) {

        while (1) {

            switch (_context.prev

= _context.next) {

                case 0:

                    i = 0;

                    j = 2;

                case 2:

                    if (!true) {

                        _context.next = 9;

                        break;

                    }

                    _context.next

= 5;

                    return i++;

                case 5:

                    if (j--) {

_context.next = 7;

                        break;

                    }

                    return

_context.abrupt("return", 100);

                case 7:

                    _context.next

= 2;

                    break;

                case 9:

                case

"end":

                    return _context.stop();

            }

        }

    }, _marked, this);

}

var gen = inc();

for (var i = 0; i < 10; i++) {

    console.log(gen.next());

}

預設必須寫在外頭,函數和類。

5、預設

有presets,預設的一些

6、轉義安裝配置****

1)建立檔案夾src 和lib

将導入和導出檔案放入src檔案中。

目錄下打開shell  敲入指令npm init 生成package.json檔案。

2)設定鏡像

.npmrc檔案

echo

"registry=https://registry.npm.taobao.org" > .npmrc

3)安裝

項目根目錄下。

$

npm install babel-core babel-cli 

--save-dev

安裝完成後,會在項目根目錄下出現node_moudles

4)修改package.json檔案

"name": "trans",

"version": "1.0.0",

"description": "trans test",

"main": "index.js",

"directories": {

"lib": "lib"

  },

"scripts": {

"build": "babel src -d lib"

  },

"author": "",

"license": "ISC",

"devDependencies": {

"babel-cli": "^6.26.0",

    "babel-core": "^6.26.3"

  }

}

替換為這樣的。

"build": "babel src -d

lib"   的意思是從src目錄轉義後輸出到lib目錄。

7、準備目錄

項目根目錄下建立src和lib目錄。

Src是源碼目錄。

Lib是目标目錄

8、配置babel和安裝依賴

touch

.babelrc  建立此檔案,内容如下 

.babelrc沒有字尾

{

“presets”:["env"]

}

Env是目前環境自動選擇。

安裝依賴

npm

install babel-preset-env  -save-dev

9、準備js檔案

export default function a(){

    console.log(\'a is t1.a()\')

};

export function b(){

    console.log(\'t1.b()\')

};

export 

let c = 100;

export 

var d = 200;

export const e = 300;

import a from \'./mod\'

a();

在項目根目錄下:

$

npm run build

>

[email protected] build C:\Users\WCL\Documents\trans    //

>

babel src -d lib                         

//

src\index.js

-> lib\index.js       //

src\mod.js

-> lib\mod.js           //

兩個檔案被轉譯。

運作檔案:

$

node lib/index.js

a

is t1.a()

使用babel轉譯工具轉譯js非常流行。

可以提高開發效率,相容性交給轉移器處理。

lib

下的index轉譯後的檔案格式:

\'use

strict\';

var

_mod = require(\'./mod\');

var

_mod2 = _interopRequireDefault(_mod);

function

_interopRequireDefault(obj) { return obj && obj.__esModule ? obj : {

default: obj }; }

(0,

_mod2.default)();

Mod的檔案;

\'use

strict\';

Object.defineProperty(exports,

"__esModule", {

    value: true

});

exports.default

= a;

exports.b

= b;

//

function a(){

//     console.log(\'test\')

//

}

//

export default

function

a() {

    console.log(\'a is t1.a()\');

};

function

b() {

    console.log(\'t1.b()\');

};

var

c = exports.c = 100;

var

d = exports.d = 200;

var

e = exports.e = 300;

10、導入導出

導出檔案代碼全部在src下的mod.js檔案,導入檔案都在index.js檔案下

export default function a(){

    console.log(\'a is t1\')

};

//預設導出,匿名函數

export default function(){

    console.log(\'default export function\')

}

a();

//預設導入

import defaultFunc from \'./mod\'

defaultFunc();

預設導入的時候,可以自己重新命名,不需要和預設導出 的時候一緻。

預設導入,不需要在import後使用花括号。

/**

 * 導出舉例

 */

//預設導出類

export default class{

    constructor(x){

        this.x = x;

    }

    show(){

        console.log(this.x)

    }

}

//命名導出函數

export function foo(){

    console.log(\'regular foo()\')

}

//函數定義

function bar(){

    console.log(\'regular bar()\')

}

//變量常量定義

let x= 100;

var b = 200;

const z=300;

export {bar,x ,y,z};

/**

 * 導入

 */

import defaluts,{foo,bar,x,y,z as CONST_c}from \'./mod\'

foo();

bar();

console.log(x);

console.log(y);

console.log(CONST_c);

new defaluts(100).show();

導入所有的導出,會使用一個新的名詞空間,使用名詞空間可以避免沖突。

Import * as newmod from ‘./mod’;

Newmod.foo();

Newmod.bar();

New newmod.default(200).show();

七、解構

Js的參數解構參考文檔;

https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/Spread_syntax

1、清單解構

var a = [1,2,3,4,5,6]

var b = [...a,7,8,9,0]

console.log(b)

[ 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 ]

2、參數解構

//參數

function f(x,y,z){

    console.log(x+y+z)

}

var args = [1,2,3,4]

f(...args);

結果為6,按照位置一一對應參數,多了的參數不用管,少的參數直接為undefined。

3、數組

解構的時候也是利用數組進行接數值。

//數組解構

const arr = [1,2,3]

let [x,y,z] = arr

console.log(x,y,z)

//丢棄元素

const [,b,] = arr

console.log(b)

//少于數組元素

const[c,d] = arr

console.log(c,d)

//多餘數組元素

const[e,f,g,h] = arr

console.log(e,f,g,h)

//可變變量

const[i,...args] = arr

console.log(i)

console.log(args)    //可變的參數args收集多個,利用的數數組

//支援預設參數

const[k=20,l=34,,,p=222] = arr

console.log(k,l,p)       //沒有的話預設使用預設參數,有的話優先使用數組的元素

數組,可變參數的收集就是數組。

可變參數不能給預設值。

可以丢棄,參數可以多,可以少,少的全部使用undefined。

4、對象解構

const obj = {

    a:100,

    b:200,

    c:300

};

//let {x,y,z} = obj;

//console.log(x,y,z) //undefined undefined undefined  名字要與之對應的。

let {a,b,c} = obj

console.log(a,b,c)    //名字是key的名字, 100,200,300

//let {a:x,b:y,c:z} = obj  //設定别名,

//console.log(a,b,c)

//console.log(x,y,z)    //利用别名列印出消息

//預設值

let {a:x,b:y,c:z=\'abc\'} = obj

console.log(x,y,z)

結構的時候,提供對象的屬性名(key),可以根據屬性名找到對應的值,

沒有找到對應的值使用預設值,沒有預設值的話就是undefined,也可以采用别名的方式,把key改成别名,通過别名進行通路屬性的值。

别名:

Obj解構。

5、複雜結構

(1)嵌套的數組:

const arr = [1,[2,3],4]

const [a,[b,c],d] = arr

console.log(a,b,c,d)    //1 2 3 4

const [e,f] = arr

console.log(e,f)  //嵌套的可以接一個數組,作為外層的一個元素。

                    //1 [ 2, 3 ]

let [g,h,i,j=19] = arr

console.log(g,h,i,j)    //1 [ 2, 3 ] 4

19

var [k,...l] = arr

console.log(k,l)   //1 [ [ 2, 3 ],

4 ]

(2)對象

var atim = {

    title:\'secation\',

    tranliat:[

        {

        local:\'def\',

        local_tart:[],

        last_dict:\'2222222\',

        url:\'/def/ac/asd/ffff\',

        titile:\'java\'

        }

    ],

    url:\'wwwww.xxxxxx.com\'

}

// let {titile,tranliat,url} = atim

// console.log(titile,tranliat,url)

let{titile,tranliat:[{local}],url} = atim

console.log(local)

還是利用屬性名(key)查詢所對應的值。

6、數組的操作

方法 描述
Push(…items) 尾部增加多個元素
Pop() 移除最後一個元素,并傳回
Map 引入處理函數中來處理數組中的每一個元素,傳回新的數組
Filter 引入處理函數處理數組中的每一個元素,此處理函數傳回true的元素保留,否則該元素被過濾掉了,保留的元素構成新的數組傳回。
Foreach 疊代所有元素,無傳回值

const arr = [1,2,3,4,5,6]

arr.push(6,7,8,9,0)

console.log(arr)

arr.pop()

console.log(arr)

const newarr = arr.map(x=>x*x)

console.log(newarr)

let newarr1 = arr.filter(x=>x%2==0)

console.log(newarr1)

let newarr2 = arr.forEach(x=>x+1)

console.log(newarr2)  //沒有新的傳回值

練習題:

s = Math.sqrt(10)

const arr = [1,2,3,4,5]

//console.log(arr.filter(x=>x%2==0 && x>3).map(x=>x*x))

//console.log(arr.filter(x=>x>s && x%2==0).map(x=>x*x))

let newarr = []

arr.forEach(x=>{

    if (x>s && x%2==0) newarr.push(x*x)

})

console.log(newarr)

map傳回每次都會傳回一個新的值。

filter過濾解決,傳回一個新的。

foreach疊代元素,沒有任何傳回值,傳回新的結果是采用新的數組。

資料算數的問題:能過濾先過濾,先過濾在進行計算。

7、對象操作

Object靜态方法 描述資訊
Object.keys(obj) Es5開始,傳回所有的key
Object.values(obj) 傳回所有值
Object.entries(obj) 傳回所有值
Object.assign(target,…sources) 使用多個source對象,來填充target對象,傳回target對象

const obj = {

    a:100,

    b:200,

    c:300

};

console.log(Object.keys(obj));

console.log(Object.values(obj)) 

console.log(Object.entries(obj))  //二進制數組

var atim = {

    title:\'secation\',

    tranliat:[

        {

        local:\'def\',

        local_tart:[],

        last_dict:\'2222222\',

        url:\'/def/ac/asd/ffff\',

        titile:\'java\'

        }

    ],

    url:\'wwwww.xxxxxx.com\'

}

var copy = Object.assign(

    {},atim,{

       name:\'xxxxxx\',url:\'www.xxxx.com\'

    },{tranliat:null}

)

console.log(copy)

{ title: \'secation\',

  tranliat: null,

  url: \'www.xxxx.com\',

  name: \'xxxxxx\' }

屬性和值的動态增加和替換等,傳回新的。

八、promise

1、概念

Promise對象用于一個異步操作的最終完成(包括成功和失敗,)即結果值的表示。

處理異步請求,之是以叫做promise,就是承諾,如果成功怎麼處理,失敗怎麼處理。

文法格式:

new promise(

//executor函數

function(resolve,reject){….});

(1)executor

是一個帶有resolve和reject兩個參數的函數,

Executor函數在promise構造函數執行同步執行,被傳遞resolve和reject函數(execu函數在promise構造函數傳回前被調用)

Executor内部通常會執行一些異步操作,一旦成功,可以調用resolve函數将promise狀态改成fulfilled即完成,或者在發生錯誤的時候将其狀态改為rejected失敗

如果在executor函數中抛出一個錯誤,那麼該promise狀态為rejected,executo函數的傳回值被忽略。

Executor中,resolve或者reject函數隻能執行一個。

(2)promise狀态

Pending初始狀态,不是成功和失敗的狀态

Fulfilled意味成功

Rejected,意味着失敗了。

(3)promise.then(onfulfilled,Onrejected)

參數是兩個函數,根據promise的狀态來調節不同的函數,fulfilled走的是onfulfiled,reject走的Onrejected。Then得傳回值是一個新的promise對象,調用任何一個參數後,其傳回值會被新的promise對象來resolve向後傳遞,

var myPromise = new Promise((resolve,reject)=>{

    resolve(\'ok\')

    console.log(\'======\')

    reject(\'no\') 

//不會執行到

})

console.log(myPromise);

myPromise.then(

    (value)=>console.log(1,myPromise,value),

    (reason)=>console.log(2,myPromise,reason)

)

======

Promise { \'ok\' }

1 Promise { \'ok\' } \'ok\'

(4)catch(onrejected)

為目前promise對象添加一個拒絕回調,傳回一個新的promise對象,onrejected函數調用其傳回值會被新的promise對象用來resolve。

var myPromise = new Promise((resolve,reject)=>{

    resolve(\'ok\')

    console.log(\'======\')

    reject(\'no\')

})

console.log(myPromise);

//鍊式處理

myPromise.then(

    /**

    成功就會顯示結果

     */

    (value)=>console.log(1,myPromise,value),

    /**

     * 失敗就顯示原因

     */

    (reason)=>console.log(2,myPromise,reason)

).then(

    function(v){

        console.log(2.5,v);

        return Promise.reject(v+\'++++++\')

    }

).catch(reason=>{

    console.log(3,reason)

    return Promise.resolve(reason)

})

(5)異步調用執行個體

function runAsync(){

    return new Promise(function(resolve,reject){

        setTimeout(function(){

            console.log(\'do sth...\')

            resolve(\'ok...\')

        },3000);

    })

}

runAsync().then(value=>{

    console.log(value)

    return Promise.reject(value+\'*\')

}).catch(reason=>{

    console.log(reason)

    return Promise.resolve(reason+\'*\')

}).then(value=>{

    console.log(value)

    console.log(\'end\')

})

console.log(\'----fin-----\')

----fin-----

do sth...

ok...

ok...*

ok...**

end

不會阻塞執行,按照順序執行,順序執行後按照要求進行排程處理。

嚴格模式:定義常量時候必須使用var這些等。

js前端技術