HTML(hypertext markup language)超文本標記語言,不一樣於編程語言。css
超文本就是超出純文本的範疇,描述文本的顏色、大小、字體。html
HTML由一個個標籤組成,標籤各司其職,有的提供網頁信息,有的負責圖片,有的負責網頁佈局。前端
超文本須要顯示,就得有軟件呈現超文本定義的排版格式,,例如顯示圖片、表格、顯示字體的大小,顏色,軟件就是瀏覽器。java
超文本的誕生是爲了解決純文本不能格式顯示問題,是爲了好看,可是隻用經過網絡分享超文本的內容,因此制定了HTTP協議。node
1)歷史、1980年代,tim berners-Lee爲cern設計基於超文本思想的enquire,以促進科研人員之間信息更新和共享。19899年其編寫了《信息化管理;建議》一文,並構建基於Internet的hypertext系統,並在cern開發了world wide web項目。打造了世界上第一站。於1991年8月6日上線。jquery
Tim berners-lee於1990年發明了第一個瀏覽器,還發明瞭HTTP協議。linux
1994年MIT建立了w3c。w3c萬維網聯盟,負責萬維網持續發展,提出w3c的標準應該基於無專利權、無版稅。c++
Marc Andreessen於1993年發明了mosaic瀏覽器,看到了技術前景,不久後成立本身的公司---網景公司Netscape,1994發不了Netscape navigator瀏覽器,席捲全球。es6
1995年微軟發佈IE。web
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等框架來解決兼容性問題。
是一種動態的弱類型的腳本解釋性語言。和HTML、css秉承三大web核心技術。
ECMAscript:是ecma國際組織
JavaScript是商品名。
2009年 ES5發佈
2015年ES6發佈
谷歌推出的,使用的是bsd協議開源。
Nodejs是服務器端運行JavaScript的開源、跨平臺運行環境。
做者是瑞安達爾(ryan dahl),2009年發佈,使用了v8引擎,採用時間驅動,非阻塞,異步IO模型。
2012年,npm軟件包管理器誕生,經過其,能夠方便的發佈,分享nodejs的庫和源代碼。
Nodejs4.0引入了ES6語言的特性。
國內阿里雲鏡像
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
默認路徑安裝:
Visual studio code
https://code.visualstudio.com/Download
和c、Java同樣
//單行註釋
/*comment*/ 多行註釋,在語句中間使用。
str = 'hello' + /*comment*/ 'student'
標識符
標識符必須是字母、下劃線、美圓符號和數字,但必須是字母、下劃線、美圓符號開頭。,不能是數字開頭。
標識符區分大小寫。
聲明
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)
序號 |
名稱 |
說明 |
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.
若是運算符是邏輯運算符,短路符,返回的就是短路時候的類型,沒有隱士轉換,
儘可能使用顯示的轉換。
將一個值利用單引號或者雙引號引發來就是字符串。
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
名稱 |
說明 |
\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的簡寫。 |
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
在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()) //隨機數
+ - * / %
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
不作隱士的類型轉換寫的是===。
不作兩個等等號。嚴格相等使用三個等號。
console.log(100 > '200') // false
console.log(100 > 'a') //false
console.log(300 == '300') //true
console.log(300 === '300') //false
&&,||,! 與或非
& | ^ ~<< >>位與,位或,異或,取反,左移,右移。
條件表達式?真值:假值
console.log(('3' > 30)?'真':'假')
Js運行多個表達式寫在一塊兒
let a = 4+5,b = true,c=a > 20?'t':'f'
console.log(a) // 9
console.log(c) // f
名稱 |
說明 |
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刪除對象、屬性、數組元素
運算符由高到低。
var trees = new Array();
逗號運算符優先級最低,比賦值語句還低。
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。
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塊做用域,外部能夠見到,普通定義外部也可見。
if (cond1){
}
else if(cond2){
}
else if (cond3){
}
else{
}
條件False等效
False
Undefined
Null
0
NaN
空字符串(」」)
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語句均可以協程多分支結構。
//for ([initialExpression];[condition];[increamentExpression])
//{
// statement
//}
for (let i=0;i<10;i++){
console.log(i)
}
console.log('---')
五、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)
}
對象操做語句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
0
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循環操做簡單。
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中斷當前煦暖,直接進入下一次循環。
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退出的時候仍是會加一或減一。
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())
高階函數:函數做爲參數或者返回一個函數。
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
}));
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;
}));
傳參是按照位置對應的,沒有關鍵字傳參這個屬性。寫的像的話只是賦值語句。
傳參的是隻是表達式的值。
數組不解構的話當作一個來進行,解構利用…
缺省值能夠進行定義的。位置傳參的,缺省值日後寫
//位置傳參
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
const sum = function(...args){
let resule = 0;
for (i in args){
resule += args[i]
};
return resule
};
console.log(sum(2,3,4))
可變參數使用…args.
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,鍵值對的字典裏面。
const add = function (x,y){
return x+y
}
console.log(add(...[100,200,300,400,500])) //參數解構,不須要參數一一對應的。
參數解構,不須要和須要的參數一一對應。
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());
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是基於原型的語言,只有原型對象的概念,原型對象就是一個模板,新的對象從這個對象模板構建從而獲取最初的屬性,任何對象在運行時候能夠動態的增長屬性。任何一個對象均可以做爲另外一個對象的原型,後者就能夠共享前者的屬性。
var obj = {
}
var obj1 = new Object();
var obj2 = new Object;
建立的時候必須使用new方法。
function定義的時候 大駝峯。
字面聲明方式。
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不表明實例。
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()
屬性優先,必定先用屬性。優先使用子類的屬性。
總結:若是子類和父類使用同一種方式進行定義,子類覆蓋父類的。
若是父類使用的屬性,子類使用的是方法,那麼就是採用父類的屬性。
若是子類使用的屬性,父類是方法,那麼優先使用的是子類的屬性方法。。
最終總結,屬性優先。。同一類定義的,子類優先
靜態屬性:
靜態方法沒有很好的支持的。
在方法名前面加上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方法訪問靜態方法。
靜態成員必須使用類來定義的。
實例是本身的。
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。
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技術。
使用throw關鍵字拋出異常。
使用throw關鍵字能夠拋出任意對象的異常
try…catch語句捕獲異常
try….catch…finally ,語句捕獲異常,finally保證最終必定執行。
try{
throw 1;
}catch (error){
console.log(error.constructor.name);
}finally{
console.log('end')
}
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,儘量的懶加載。
Import語句,導入另外一個模塊導出的綁定。
Export語句,從模塊中導入函數、對象、值,供其餘模塊import導入引用。
創建模塊的目錄src,此目錄下創建mode.js, 內容是導入和導入模塊的代買
export default function a(){ //導出缺省的
console.log('a is t1')
};
a();
//導出函數
Export function foo(){
Console.log(‘foo function’);
}
//導出常量
Export const consta = ‘aaa’
import a from './t1-1'
a();
vs code能夠很好的語法支持,可是運行環境和v8引擎,不能很好的支持模塊化語法。
轉譯從一種語言代碼轉換到另外一語言代碼,固然也能夠從高版本轉譯到低版本的支持語句。
因爲js存在不一樣的版本,不一樣瀏覽器兼容問題,使用transpiler轉譯工具解決。
Babel
開發中比較新的es6的語法,經過轉移器指定Wie特定的某些版本代碼。
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());
}
缺省必須寫在外頭,函數和類。
有presets,預設的一些
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目錄。
項目根目錄下建立src和lib目錄。
Src是源碼目錄。
Lib是目標目錄
touch .babelrc 建立此文件,內容以下 .babelrc沒有後綴
{
「presets」:["env"]
}
Env是當前環境自動選擇。
安裝依賴
npm install babel-preset-env -save-dev
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
> trans@1.0.0 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;
導出文件代碼所有在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
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 ]
//參數
function f(x,y,z){
console.log(x+y+z)
}
var args = [1,2,3,4]
f(...args);
結果爲6,按照位置一一對應參數,多了的參數不用管,少的參數直接爲undefined。
解構的時候也是利用數組進行接數值。
//數組解構
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。
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解構。
(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)查詢所對應的值。
方法 |
描述 |
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迭代元素,沒有任何返回值,返回新的結果是採用新的數組。
數據算數的問題:能過濾先過濾,先過濾在進行計算。
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對象用於一個異步操做的最終完成(包括成功和失敗,)即結果值的表示。
處理異步請求,之因此叫作promise,就是承諾,若是成功怎麼處理,失敗怎麼處理。
語法格式:
new promise(
//executor函數
function(resolve,reject){….});
是一個帶有resolve和reject兩個參數的函數,
Executor函數在promise構造函數執行同步執行,被傳遞resolve和reject函數(execu函數在promise構造函數返回前被調用)
Executor內部一般會執行一些異步操做,一旦成功,能夠調用resolve函數將promise狀態改爲fulfilled即完成,或者在發生錯誤的時候將其狀態改成rejected失敗
若是在executor函數中拋出一個錯誤,那麼該promise狀態爲rejected,executo函數的返回值被忽略。
Executor中,resolve或者reject函數只能執行一個。
Pending初始狀態,不是成功和失敗的狀態
Fulfilled意味成功
Rejected,意味着失敗了。
參數是兩個函數,根據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'
爲當前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)
})
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這些等。