一、前端技術
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這些等。