1.js誕生於1997年,Brendan Eich10天設計出來的,當時java很火,爲了蹭熱度,網景公司將其取名爲JavaScript,兩者除了語法有點像,啥關係都沒有。
2.ECMAScript是一種語言標準,JavaScript是網景公司對ECMAScript標準的一種實現。
3.直接在硬盤上創建好HTML和Javascript文件,然後用瀏覽器打開,這種方式運行部分js代碼沒問題,但由於瀏覽器的安全限制,以file://開頭的地址無法執行如聯網等js代碼,最終,我們還是需要架設一個web服務器,然後以http://開頭的地址來正常執行所有js代碼。
4.js嚴格區分大小寫。
5.相等運算符:== 會自動轉換數據類型再比較,很多時候,會得到非常詭異的結果; === ,不會自動轉換數據類型,如果數據類型不一致,返回false,如果一致,再比較。由於這個設計缺陷,不要使用==比較,使用===比較。
6.js數據類型Number、String、Boolean、Null、undefined、symbol、Object
1)Number:數字類型,js不區分整數和浮點數,統一用Number表示,infinite,無限大,當數字計算後超出Number所能表示的最大值時,用infinite表示比如2/0,可以對任何數字調用isFinite()以確保該數不是無窮大,還有個特殊的NaN,表示非數(not a number),一般來說,得出NaN是在類型轉換失敗時,NaN和自身也不相等,做判斷時可用isNaN().
2)String:字符串,由‘’和“”表示,字符串中出現’或“可以使用轉義符\進行轉義,例如'I\'m'==I'm;多行字符串可以使用反引號``,這是es6新增的字符串模板,在模板中,也能使用${name}來填寫變量數據,字符串可以使用下標來獲取對應位置的字符,但是字符串是不可更改的,所以使用下標來改變字符串是無效的(s[0]='a'),但不會報錯,字符串常用函數:toUpperCase()字符串大寫,toLowerCase()字符串轉成小寫,indexOf()返回指定字符首次出現的位置,沒有返回-1,substring()截取區域字符。
3)array:數組,可以包含任意數據類型,並通過索引來訪問每個元素。直接給array的length賦值,會改變數組的長度,新增的數組元素是undefined,通過索引賦值時,如果索引超出數組長度,同樣會改變數組的長度,其他新增的元素是undefined,數組常用函數:indexof()返回某個元素在數組中首次出現的位置,沒有返回-1,slice()類似與字符串的substring,截取指定區域的數組元素,返回一個新的array,slice的起止參數包換開始索引,不包含結束索引,如果slice沒有參數,它會從頭到尾截取所有參數,利用這一點,可以複製一個數組。push和unshift向數組的結尾或開始添加數個元素,pop和shift刪除數組的結尾或開始的第一個元素,sort()排序功能,reverse()反轉整個數組,splice()從指定位置刪除若干元素,再從該位置添加若干元素。concat()拼接任意數組,join()將數組的元素由指定字符鏈接起來,返回鏈接後的字符串。
4)對象是一種無序的集合數據類型,它由若干鍵值對組成,鍵值對以逗號隔開,使用 . 或 [ ] 來訪問屬性字符時要用引,當鍵名包含特殊號‘’擴起來並且無法使用 . 來訪問,只能用 ['xxx'] 來訪問,js的對象是一種動態類型,可以自由添加或刪除屬性:delete刪除:delete object['xxx']; 檢測對象中是否存在某一屬性可以使用in或hasOwnPropert()方法: ’name' in xiaoming 或xiaoming.hasOwnPropert('name'),in不僅判斷對象本身它還會判斷對象繼承到的。
8.變量名不能是數字開頭,也不能是js的關鍵字。
9.strict模式,當一個變量沒有通過var聲明就被使用,那麼該變量就自動被聲明爲全局變量,同名變量在一個頁面會互相沖突覆蓋,所以我們需要用var來聲明一個非全局變量,把它的返回限制在該變量被申明的函數體內,同名變量在不同的函數體內互不衝突。使用strict模式,會強制通過var申明變量,未使用var申明變量就使用的,將導致運行錯誤。啓用strict模式的方法是在js代碼第一行寫上 “use strict”; 這是一個字符串,不支持strict模式的瀏覽器會把它當作一個字符串語句執行,支持strict模式的將開啓strict模式運行js。
10.js把null undefinde NaN 0 '' 視爲false,其他都爲true.
11.for...in..:把對象的所有屬性循環出來
var o = {a:1,b:2} ;
for(var key in o){
console.log(key)
};
12.
map:js默認對象表示方式{}是鍵值對,但鍵必須是字符串,實際上Number或其他數據類型作爲鍵也是合理的,爲解決這個問題,es6引入了新的數據類型Map。map是一組鍵值對的結構,具有極快的查找速度。
初始化map需要一個二維數組
var m = new Map([['name','God'],['sex','man']]);
m.get('name')//God
,或者直接初始化一個空Map.Map具有以下方法:
var m = new Map();//空map
m.set('name','God')//添加新的key-value
m.has('name');//是否存在key'name',true
m.get('name');//God
m.delete('name')//刪除key'name'
m.get('name');//undefined
m.clear();//清空Map
由於一個key只能對應一個value,所以,多次對一個key放入value,後面的值會把前面的值覆蓋掉。
13.
Set:Set和數組類似,不存儲value。由於key不能重複,所以,在Set中,沒有重複的key.。
要創建一個Set,需要提供一個Array作爲輸入,或者直接創建一個空Set:
var s1=new Set()//空Set
var s2 = new Set([0,1,2,3]);//含1,2,3
重複的元素在set中自動過濾
var s = new Set([0,0,1]);
s;//Set {0,1}
s.size//2
在Set內部,兩個NaN
是相等。兩個對象總是不相等的。可以用length來檢測
四個操作方法:
add(value)
:添加某個值,返回Set結構本身。delete(value)
:刪除某個值,返回一個布爾值,表示刪除是否成功。has(value)
:返回一個布爾值,表示該值是否爲Set
的成員。clear()
:清除所有成員,沒有返回值
set內部的元素可以遍歷for...of...
14.forEash,和map()方法類似,把元素作用於傳入的函數中,但不會返回新的數組,常用於便利數組。
forEash,接收一個函數,每次迭代就自動回調該函數。
var a = [1,2,3];
a.forEash(function(value,index,arr){
// value: 指向當前元素的值
// index: 指向當前索引})
15.for ...of...:循環遍歷array Map Set等iterable類型
16.函數就是最基本的一種代碼抽象的方式。
17.arguments:當前函數的調用者傳入的所有參數,類似數組但不是一個數組。
18 ...rest:當前函數除了指定的參數外,其他多餘傳入的參數以數組的形式交給變量rest,rest只能寫在最後,前面用...標識。
19.變量的作用域在自身定義的函數裏,在函數體外不可引用該變量,內部函數可以調用外部函數的變量,在查找函數變量的時候是從自身函數定義開始,由內而外,如果內部函數定義了與外部函數重名的變量,內部函數的變量將屏蔽外部函數的變量。
變量提升:js的函數定義有個特點,會先掃描整個函數體的語句,然後把所有申明的變量提升到函數頂部,但它只會提升變量的聲明,不會提升變量的賦值。
全局作用域:不再任何函數內部定義的變量就具有全局作用域。js默認有一個全局對象window,全局作用域的變量實際上是被綁定到window的一個屬性。訪問alert和訪問window.alert()是一個效果。
名字空間:全局變量都會綁定w到indow上,當全局變量使用了同一個名字就會造成命名衝突,減少衝突一個方法是把自己的變量和函數全部綁定到一個全局變量上,例如jq。
局部作用域:變量的作用域實際上是函數內部,在for等語句塊中是無法定義具有局部作用域的變量的:
function foo() {
for (var i=0; i<100; i++) {
//
}
i += 100; // 仍然可以引用變量i
}
爲解決這個問題,es6引入關鍵字let,let代替var可以申明一個塊級作用域的變量
20.解構賦值:直接對多個變量同時賦值。
對數組元素進行解構賦值,多個變量要用 [ ] 擴起來
例如:
var [x,y,z]=['a','b','c'];//x=a,y=b,z=c
或
var arr = ['a','b','c'];
var [x,y,z]=arr;
console.log(x)//a
如果數組本身還有嵌套,解構賦值時嵌套層次和位置要保持一致
例如:let [x,[y,z]] = ['a',['b','c']];//x=a,y=b,z=c;
解構賦值還可以忽略某些元素
例如:let [,,z] = ['a','b','v'] //z=v;
如果需要從一個對象中取出若干屬性,也可以使用解構賦值,便於快速獲取對象的指定屬性:
例如
var person={
name:'小明',
age:20,
sex:"男"
}
var {name,age}=person;//name=小明,age=20
對對象解構賦值,同樣可以對嵌套對象屬性進行賦值,之間要對應的層次是一致的:
例如:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school',
address: {
city: 'Beijing',
street: 'No.1 Road',
zipcode: '100001'
}
};
let {name,age,address:{city,zip}}=person;
//name=小明,age=20,city=Beijing,zip=undefined
//address不是變量,是爲了讓city和zip獲得嵌套的address對象的屬性
對象屬性使用解構賦值時,如果對應屬性不存在,變量將被賦值undefined,如果要使用的變量名和屬性名不一項可以使用屬性名:變量名
例如:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678',
school: 'No.4 middle school'
};
// 把passport屬性賦值給變量id:
let {name, passport:id} = person;
name; // '小明'
id; // 'G-12345678'
// 注意: passport不是變量,而是爲了讓變量id獲得passport屬性:
passport; // Uncaught ReferenceError: passport is not defined
解構賦值還可以使用默認值,這樣就避免了不存在的屬性返回undefined的問題:
var person = {
name: '小明',
age: 20,
gender: 'male',
passport: 'G-12345678'
};
// 如果person對象沒有single屬性,默認賦值爲true:
var {name, single=true} = person;
name; // '小明'
single; // true
有些時候,如果變量已經被聲明瞭,再次賦值的時候,正確的寫法也會報語法錯誤:
// 聲明變量:
var x, y;
// 解構賦值:
{x, y} = { name: '小明', x: 100, y: 200};
// 語法錯誤: Uncaught SyntaxError: Unexpected token =
這是因爲JavaScript引擎把{
開頭的語句當作了塊處理,於是=
不再合法。解決方法是用小括號括起來:
({x, y} = { name: '小明', x: 100, y: 200});
21.this:誰調用它,它就指向誰。
當我們要改變函數內的this指向時,使用apply或者call
22.apply(obj,array),apply指定函數的this指向,它有兩個參數,第一個參數就是需要綁定this的變量,第二個是函數本身的參數
例如:getAge.apply('person',[]);//此時getAge內部的this指向person,參數是空的數組
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 參數爲空
23.call,類似與apply,唯一的區別是,call的參數是按照順序傳入的,apply參數是按照數組傳入的。
Math.max.apply(null, [3, 5, 4]); // 5
Math.max.call(null, 3, 5, 4); // 5
24.map():array的方法,參數是一個函數,函數有三個參數(value,index,arr),,將這個函數作用於數組的每個元素上,返回一個新數組,不改變原數組。
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(String); // ['1', '2', '3', '4', '5', '6', '7', '8', '9']
25.filter():array的方法,它是一個實現篩選的高級函數,和map方法類似,接收一個函數,函數有三個參數(value,index,arr),函數作用於數組的每個元素上,不同的是,它根據返回值是false還是true來決定保留還是丟棄該元素。
var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r; // [1, 5, 9, 15]
26.reduce():array的方法,參數是一個函數,這個函數必須接收兩個值,數組中的值從左到右依次傳入這個函數裏,最後得出一個值返回出來。
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x + y;
}); // 25
27.sort():排序方法,可接受一個函數,排列順需有函數的返回值-1,0,1排序,sort方法是直接對原數組進行更改的。
var arr = [10, 20, 1, 2]; arr.sort(function (x, y) { if (x < y) { return -1; } if (x > y) { return 1; } return 0; }); console.log(arr); // [1, 2, 10, 20]
28.every():判斷數組的所有元素是否符合條件,返回一個布爾值。
var arr = ['Apple', 'pear', 'orange'];
console.log(arr.every(function (s) {
return s.length > 0;
})); // true, 因爲每個元素都滿足s.length>0console.log(arr.every(function (s) {
return s.toLowerCase() === s;
})); // false, 因爲不是每個元素都全部是小寫
29:find():查找array元素的方法,接受一個函數,函數作用於數組的每個元素,用於查找符合元素的第一個元素,如果找到了返回這個元素本身,沒有找到返回undefined;
var arr = ['Apple', 'pear', 'orange'];
console.log(arr.find(function (s) {
return s.toLowerCase() === s;
})); // 'pear', 因爲pear全部是小寫console.log(arr.find(function (s) {
return s.toUpperCase() === s;
})); // undefined, 因爲沒有全部是大寫的元素
30:findIndex():和find方法類似,返回符合查找元素的第一個元素的索引。
31:
-
不要使用
new Number()
、new Boolean()
、new String()
創建包裝對象; -
用
parseInt()
或parseFloat()
來轉換任意類型到number
; -
用
String()
來轉換任意類型到string
,或者直接調用某個對象的toString()
方法; -
通常不必把任意類型轉換爲
boolean
再判斷,因爲可以直接寫if (myVar) {...}
; -
typeof
操作符可以判斷出number
、boolean
、string
、function
和undefined
; -
判斷
Array
要使用Array.isArray(arr)
; -
判斷
null
請使用myVar === null
; -
判斷某個全局變量是否存在用
typeof window.myVar === 'undefined'
; -
函數內部判斷某個變量是否存在用
typeof myVar === 'undefined'
。
任何對象都有toString()
方法嗎?null
和undefined
就沒有!確實如此,這兩個特殊值要除外,雖然null
還僞裝成了object
類型。
number
對象調用toString()
報SyntaxError:
123.toString(); // SyntaxError
遇到這種情況,要特殊處理一下:
123..toString(); // '123', 注意是兩個點!
(123).toString(); // '123'
32.generator:es6中提供的一種異步編程解決方法,可以隨心所欲交出和恢複函數的執行權,next()恢復執行權,yield交出執行權。generator函數和普通函數寫法相似,不過他在function後加一個*號,調用時需要創造一個函數句柄,然後調用next():
function* generator(){
yield "a";
yield "b";
return "c"
}
var g=generator();//創造g對象,指向generator函數句柄
g.next();//g.value=a,g.done=false 第一次調用next(),執行到yield "a",暫緩執行,並返回 a
g.next();//g.value=b,g.done=false 繼續上一次的執行,執行到yield "b",暫緩執行,並返回b
g.next();//g.value=c,g.done=true 繼續上一次的執行,執行到return,返回 c 和 done:true,表明結束
yield關鍵字只能在generator函數中使用,起到暫緩執行的作用,每次執行一次next(),相當於指針移動到下一個yield位置。
通過yield標識符和next()方法調用,實現函數的分段執行,yield後跟*,可以調用另一個generator()函數。
出來使用.next()方法遍歷迭代器對象外,還可以使用for...of,但它會忽略return返回的值。
function* generator(){
yield "a";
yield "b";
return "c"
}
var g = generator();
for(var i of g){
console.log(i)//a,b
}
33.typeof:獲取對象類型,返回一個字符串。
typeof 123 ;//'number'
typeof NaN ;//'number'
typeof 'abc';//'string'
typeof true;//'Boolean'
typeof undefined;//'undefined'
typeof null;//'object'
typeof [1,2];//'object'
typeof {};//'object'
typeof Math.abs;//'function'
34.面向對象編程有兩個基本概念:類和實例,js沒有類和實例的概念,而是通過原型(prototype)來實現面向對象編程。
js的原型鏈和java的class區別在於它沒有class的概念,所有對象都是實例,所謂的繼承關係不過是把一個對象的原型指向另一個對象。
js對每個創建的對象都會設置一個原型,指向它的原型對象,比如:
var arr=[1,2];
arr ----> Array.prototype ----> Object.prototype ----> null
function foo(){
return 0;
}
foo ----> Function.prototype ----> Object.prototype ----> null
35.創建原型的方法
1):Object.create()方法可以傳入一個原型對象,並創建出一個基於該原型的新對象。
var Student = {
name: 'Robot',
height: 1.2,
run: function () {
console.log(this.name + ' is running...');
}
};
var xiaoming=Object.create(Student);
xiaoming.name="a"
console.log(xiaoming.name)//a
xiaoming.run();//a is running...
console.log(xiaoming.__proto__===Student)//true
2):先定義一個構造函數,再使用關鍵字new來調用這個函數,並返回一個對象:
function Student(name){
this.name=name;
}
Student.prototype.say=function(){
console.log(this.name);
}
var xiaoming = new Student('xiaoming');
xiaoming.name//xiaoming
xiaoming.say();//xiaoming
它的原型鏈:
xiaoming ----> Student.prototype ----> Object.prototype ----> null
3)class,關鍵字class是從es6開始被正式引入到js中的,使用class的定義包含了構造函數constructor和定義在原型對象上的函數,沒有functio關鍵字
class Student {
constructor(name){
this.name=name;
}
hello(){
console.log("hello!")
}
}
var xiaoming = new Student('小明');
xiaoming.name==小明;
xiaoming.hello();
class繼承也是通過class關鍵字實現的,使用extends來表示原型鏈對象來自哪裏,在子類的構造函數李使用super來調用父類的構造方法
class Student {
constructor(name){
this.name=name;
}
hello(){
console.log("hello!"+this.name)
}
}
class JuniorStudent extends Student{
constructor(name,age){
super(name);//調用父類構造函數
this.age = age;
}
run(){
console.log(this.name+"is running...")
}
}
var xiaoming = new JuniorStudent("小明");
xiaoming.run();
xiaoming.hello();
36.window 表示瀏覽器的窗口。 有innerWidth和innerHeight這兩個屬性。可以獲取瀏覽器的內部寬高。
window.innerWidth; window.innerHeight;
對應的還有outerWidth和outerHeight這兩個屬性,獲取瀏覽器窗口的整體的寬高。 window.outerWidth; window.outerHeight;
37.navigator 表示瀏覽器信息。 navigator.appName:瀏覽器名稱; navigator.appVersion:瀏覽器版本 navigator.language:瀏覽器設置的語言 navigator.platform:操作系統類型; navigator.userAgent:瀏覽器設定的Use-Agent字符串
38.screen 表示屏幕信息。 screen.width; //屏幕寬度 screen.height; //屏幕寬度 screen.colorDepth; //顏色位數
39.location 表示當前頁面的URL信息。 location.href; //獲取當前頁面URL整體信息
40.document 表示當前的頁面信息。 還可以獲取當前頁面的Cookie信息。 document.cookie;
41.history 表示頁面的歷史紀錄。 但在任何情況下不使用該對象。
42.操作DOM:
直接定位Dom:document.getElementById(); document.querySelector();
返回一組DOM:documet.getElementByClassName(); document.getElementByTagName(); document.querySelectorAll()
獲取節點下所有子節點:test.children;
獲取父節點:element.parentElement;
獲取節點下首個節點和最後一個節點:test.firstElementChild test.lastElementChild;
43.更改DOM:
innerHTML:可以直接更改一個dom節點裏的內容和內部結構
innerText:只能更改內容,也不返回隱藏元素的文本
textContent:只能更改內容,返回隱藏元素的文本
44.修改css:dom節點的style屬性對應所有的css,可以直接獲取或設置。css允許font-size這樣的名稱,但它並非js有效的屬性名,所以需要在js中改寫成駝峯式命名fontSize : p.style.fontSize="12px";
45.插入dom:
appendChild:把一個子節點添加到父節點的最後一個子節點 parentElement.appendChild(element);
insertBefore:把一個子節點天驕的父節點的某個指定子節點之前 parentElement.insertBefore(elemeng,referenceElement),子節點會插入到referenceElement之前。
46.刪除節點;removeElement,刪除子節點,首先獲取該節點本身和它的父節點,然後父節點調用removeChild刪除子節點,parentElement.remove(element); 刪除後的節點雖然不在文檔中了,但是它還在內存中,可以隨時再次被添加到其他位置
<div>
<p id='first'>First</p>
<p>Second</p>
</div>
var self = document.getElementById('first');
var parent = self.parentElement;
var remove = parent.removeElement(self);
remove === self //true 刪除後的節點雖然不在文檔樹中,但它還在內存中,可以隨時再被添加到別的位置。
46.操作文件:<input type="file">
當一個表單包換<input type="file">時,表單的enctype必須是“multipart/form-data”,method必須指定爲post,瀏覽器才能正確的編碼並以multipart/form-data格式發送表單的數據。
出於安全考慮,瀏覽器只允許用戶點擊<input type="file">來選擇本地文件,對value 直接賦值是沒有效果的,js也無法獲得文件的真實路徑。
html5的file API提供了file和fileReader兩個對象來獲取文件的信息並讀取文件
//選擇並展示一張圖片
var
fileInput = document.getElementById('tset-img-file');
info = document.getElementById('test-file-info');
preview = document.getElementById('text-img-preview');
//監聽change事件
fileInput.addEventListener('change',function(){
if(!fileInput.value){
info.innerText='未選擇文件';
return;
}
})
//獲取file引用
var file = fileInput.files[0];
//獲取file的信息
info.innerHTML=`文件名稱${file.name},大小${file.size},修改${file.lastModefiedDate}`;
if(file.type != 'image/png'){
alert('不是有效的圖片文件');
return;
}
//讀取文件
var reader = new FileReader();
//當文件讀取完成後,自動調取load函數
reader.onLoad = function(e){
var
data = e.target.result;//base64編碼格式的圖片
preview.style.backgroundImage='url(' + data + ')';
}
//以dataurl的形式讀取文件
reader.readAsDataURL(file);
47.箭頭函數:相當於匿名函數,簡化了函數定義,箭頭函數有兩種格式,一種只有一個表達式,連{...}和return都省略了,還有一種包含多條語句,這時候不能省略{...}和return:
// 兩個參數:
(x, y) => x * x + y * y
// 無參數:
() => 3.14
// 可變參數:
(x, y, ...rest) => {
var i, sum = x + y;
for (i=0; i<rest.length; i++) {
sum += rest[i];
}
return sum;
}
如果要返回一個對象並且是個單表達式時,函數體要用()括起來 x => ({foo:x})
箭頭函數修復了thie的指向,this總是指向詞法作用域,也就是外層調用者obj:
var obj = {
birth: 1990,
getAge: function () {
var b = this.birth; // 1990
var fn = () => new Date().getFullYear() - this.birth; // this指向obj對象
return fn();
}
};
obj.getAge(); // 29
48.同步和異步(詳情=》https://segmentfault.com/a/1190000007032448)
同步模式,即單線程模式,一次只能執行一個任務,函數調用後要等到函數執行結束,返回執行結果,才能進行下一個任務,如果這個任務執行事件很長,就會導致【線程阻塞】。
var x=true;
while(x);
console.log("死循環阻塞了進程");//不會執行
同步模式中如果請求時間較長,而阻塞了後面代碼的執行,體驗很不好,對於一些耗時的操作,異步模式更適合。
異步模式:可以一起執行多個任務,函數調用後不會立即分會執行結果,如果任務A的結果返回需要等待一段時間,可以先執行任務B,等到任務A的結果返回後再繼續回調。
setTImeOut( () => console.log(1) , 0 ) ;
console.log(2)
-------ouput-------------
2
1
異步任務會在當前腳本的所有同步任務執行完成後再執行,所有即使定時器的時間是0,還是會先輸入同步任務的2,再輸出異步定時器任務中的1,如果同步代碼中還有死循環,那異步任務將不會執行,因爲同步任務阻塞了進程。
回調函數是一段可執行的代碼段,它以參數的形式傳遞給其他代碼,在其合適的時間執行這段代碼。
49.Promise:promise對象用於異步操作,它表示一個尚未完成且預計在未來完成的異步操作,不關心結果如何處理,根據結果的成功或失敗,將來在某個時候電泳resolv函數或reject函數
new Promise(function(resolve,reject){
var a = Math.random() *2;
return a>1?resolve('ok'):reject('fail');
})
.then(result => console.log('resolve'))
.catch(reason => console.log('reject'))
Promise一旦新建就會立即執行,無法取消,這也是他的確定之一。
Promise類似構建對象,我們使用new來構建一個Promise對象,Promise接受一個函數作爲參數,該函數有兩個參數分別是resolve和reject。這兩個函數就是回調函數,由js引擎提供。
resolve函數:在異步操作成功時調用,並將異步操作的結果作爲參數傳遞出去。
reject函數:在異步操作失敗的時候調用,並將異步操作報錯的信息作爲參數傳遞出去。
Promise實例生成後,可以用then和catch方法分別指定resolve狀態和reject狀態的回調函數。
49:宏任務與微任務與event loop:==》》https://blog.csdn.net/lc237423551/article/details/79902106
常見的宏任務有:script、setTimeout、SetInterval
微任務:premise、process.nextTick
event loop:同步和異步任務分別會進入不同的執行場所,同步任務進入主線程,異步進入event table 並註冊異步的回調函數,當異步裏的事情完成後,event table會將異步的回調函數移入event queue。主線程的任務執行任務完成後,回去event queue中讀取對應的函數,進入主線程。上述過程會不斷重複,也就是常說的Event Loop(事件循環)。
只有一個宏任務完成後(包括其中的微任務)纔會執行下一個宏任務。