學習js遇到的疑問和js基礎都記錄在這裏,持續更新中。javascript
/b+/g 至少出現一次b(1~n次)php
/b*/g 能夠不出現b,也能夠出現一次或屢次(0~n次)css
/b{n,m}/g 最少出現n次b,最多出現m次b(n~m次)html
/colou?r/g 能夠匹配color或colour,?表示前面的字符最多隻出現一次(0次或1次)前端
1.全局變量不會被回收java
2.局部變量會被回收,也就是函數一旦運行完之後,函數內部的東西都會被銷燬node
3.只要被另一個做用域所引用就不會被回收jquery
基本數據類型:undefined、null、string、number、boolean、symbolios
複雜數據類型:objectes6
引用類型:array、function、object
typeof
對一個值使用typeof操做符可能返回:
undefined、string、number、boolean、symbol、object(對象或null)、function
console.log(typeof 2); // number console.log(typeof true); // boolean console.log(typeof 'str'); // string console.log(typeof []); // object []數組的數據類型在 typeof 中被解釋爲object console.log(typeof function(){}); // function console.log(typeof {}); // object console.log(typeof undefined); // undefined console.log(typeof null); // object null 的數據類型被 typeof 解釋爲 object
instanceof
只有引用數據類型(Array,Function,Object)被精準判斷,其餘(數值Number,布爾值Boolean,字符串String)字面值不能被instanceof精準判斷。
console.log(2 instanceof Number); // false console.log(true instanceof Boolean); // false console.log('str' instanceof String); // false console.log([] instanceof Array); // true console.log(function(){} instanceof Function); // true console.log({} instanceof Object); // true // console.log(undefined instanceof Undefined); // console.log(null instanceof Null);
constructor
console.log((2).constructor === Number); // true console.log((true).constructor === Boolean); // true console.log(('str').constructor === String); // true console.log(([]).constructor === Array); // true console.log((function() {}).constructor === Function); // true console.log(({}).constructor === Object); // true
用costructor來判斷類型看起來是完美的,然而,若是我建立一個對象,更改它的原型,這種方式也變得不可靠了。
function Fn(){}; Fn.prototype = new Array(); var f = new Fn(); console.log(f.constructor === Fn); // false console.log(f.constructor === Array); // true
object.prototype.toString.call()
console.log(Object.prototype.toString.call(2)); // [object Number] console.log(Object.prototype.toString.call(true)); // [object Boolean] console.log(Object.prototype.toString.call('str')); // [object String] console.log(Object.prototype.toString.call([])); // [object Array] console.log(Object.prototype.toString.call(function(){})); // [object Function] console.log(Object.prototype.toString.call({})); // [object Object] console.log(Object.prototype.toString.call(undefined)); // [object Undefined] console.log(Object.prototype.toString.call(null)); // [object Null]
使用 Object 對象的原型方法 toString ,使用 call 進行狸貓換太子,借用Object的 toString 方法結果精準的顯示咱們須要的數據類型。就算咱們改變對象的原型,依然會顯示正確的數據類型。
詳細請看這篇文章:https://www.cnblogs.com/humin...
with、try...catch、eval
Ajax技術核心就是XMLHttpRequest對象。
(1)設置請求參數(請求方式,請求頁面的相對路徑,是否異步)
(2)設置回調函數,一個處理服務器響應的函數,使用 onreadystatechange ,相似函數指針
(3)獲取異步對象的readyState 屬性:該屬性存有服務器響應的狀態信息。每當 readyState 改變時,onreadystatechange 函數就會被執行。
(4)判斷響應報文的狀態,若爲200說明服務器正常運行並返回響應數據。
(5)讀取響應數據,能夠經過 responseText 屬性來取回由服務器返回的數據。
var xhr = new XMLHttpRequest(); // 建立Ajax對象 xhr.open('get', 'aabb.php', true); // xhr發送請求 xhr.send(null); xhr.onreadystatechange = function() { // xhr獲取響應 if(xhr.readyState == 4) { if(xhr.status == 200) { console.log(xhr.responseText); } } } /* ajax返回的狀態: 0:(未初始化)請求尚未創建(open執行前) 1:(載入)請求創建了還沒發送(執行了open) 2:(載入完成)請求正式發送,send()方法執行完成,已經接收到所有響應內容(執行了send) 3:(交互)請求已受理,有部分數據能夠用,但尚未處理完成,正在解析響應內容 4:(完成)響應內容解析完成,能夠在客戶端調用了 */
Ajax:
ajax,最先出現的發送後端請求技術,隸屬於原始js中,核心使用XMLHttpRequest對象,多個請求之間若是有前後關係的話,就會出現回調地獄。
Jquery Ajax:
是jQuery框架中的發送後端請求技術,因爲jQuery是基於原始的基礎上作的封裝,因此,jquery Ajax天然也是對原始ajax的封裝
$.ajax({ type: 'POST', url: url, data: data, dataType: dataType, success: function () {}, error: function () {} });
優缺點:
Fetch:
fetch號稱是AJAX的替代品,是在ES6出現的,使用了ES6中的promise對象。Fetch是基於promise設計的。Fetch的代碼結構比起ajax簡單多了,參數有點像jQuery ajax。
可是,必定記住fetch不是ajax的進一步封裝,而是原生js。Fetch函數就是原生js,沒有使用XMLHttpRequest對象。
try { let response = await fetch(url); let data = response.json(); console.log(data); } catch(e) { console.log("Oops, error", e); }
axios:
axios不是原生JS的,須要進行安裝,它不但能夠在客戶端使用,並且能夠在nodejs端使用。Axios也能夠在請求和響應階段進行攔截。一樣也是基於promise對象的。
https://blog.csdn.net/Roselan...
axios({ method: 'post', url: '/user/12345', data: { firstName: 'Fred', lastName: 'Flintstone' } }) .then(function (response) { console.log(response); }) .catch(function (error) { console.log(error); });
優缺點:
"/ /"這個是固定寫法,"s"是轉移符號用以匹配任何空白字符,包括空格、製表符、換頁符等等,"g"表示全局匹配將替換全部匹配的子串,若是不加"g"當匹配到第一個後就結束了。
這個例子的意思就是將原字符串中的全部空白字符替換成"",好比"abc d efg "字樣的字符串使用這個函數後將變成"abcdefg"
通常用來把字符串中全部的空格去掉
forEach()
: 數組中的每一個元素執行一次回調函數map()
: 返回一個由原數組中的每一個元素調用一個指定方法後的返回值組成的新數組示例
下方提供了一個數組,若是咱們想將其中的每個元素翻倍,咱們可使用map
和forEach
來達到目的。
let arr = [1, 2, 3, 4, 5];
ForEach
注意,forEach
是不會返回有意義的值的。
咱們在回調函數中直接修改arr
的值。
arr.forEach((num, index) => { return arr[index] = num * 2; });
Map
let doubled = arr.map(num => { return num * 2; });
indexOf() 方法可返回某個指定的字符串值在字符串中首次出現的位置,若是沒有找到返回-1
search方法用於檢索字符串中指定的子字符串,檢索與正則表達式相匹配的子字符串。若是沒有找到,返回-1。
indexOf與search的區別
search()的參數必須是正則表達式,而indexOf()的參數只是普通的字符串。indexOf()是比search()更加底層的方法。
若是隻是對一個具體字符串來檢索,那麼使用indexOf()的系統資源消耗更小,效率更高;若是查找具備某些特徵的字符串(例如查找以a開頭,後面是數字的字符串),那麼indexOf()就無能爲力,必需要使用正則表達式和search()方法了。
大可能是時候用indexOf()不是爲了真的想知道子字符串的位置,而是想知道長字符串中有沒有包含這個子字符串。r若是返回索引爲-1,那麼說明沒有,反之則有。
slice() 方法可提取字符串的某個部分,並以新的字符串返回被提取的部分。
stringObject.slice(start,end)
substring() 方法用於提取字符串中介於兩個指定下標之間的字符。
stringObject.substring(start,stop)
substr() 方法可在字符串中抽取從 start 下標開始的指定數目的字符。
stringObject.substr(start,length)
String 對象的方法 slice()、substring() 和 substr() (不建議使用)均可返回字符串的指定部分。slice() 比 substring() 要靈活一些,由於它容許使用負數做爲參數。slice() 與 substr() 有所不一樣,由於它用兩個字符的位置來指定子串,而 substr() 則用字符位置和長度來指定子串。
還要注意的是,String.slice() 與 Array.slice() 類似。
slice() 方法可從已有的數組中返回選定的元素。
arrayObject.slice(start,end)
splice() 方法主要用途是向數組的中部插入項。
arrayObject.splice(index,howmany,item1,.....,itemX)
index | 必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。 |
---|---|
howmany | 必需。要刪除的項目數量。若是設置爲 0,則不會刪除項目。 |
item1, ..., itemX | 可選。向數組添加的新項目。 |
語法:Obejct.assign(target,...sources)
用途:未來自一個或多個源對象中的值複製到一個目標對象,它將返回目標對象。其中對象的繼承屬性和不可枚舉屬性是不能拷貝的,因此不能使用它來實現深拷貝。
第一級屬性深拷貝,從第二級屬性開始就是淺拷貝。
若是多個源對象具備同名屬性,則排位靠後的源對象會覆蓋排位靠前的。但null或undefined被視爲空對象同樣對待,不會覆蓋。
var receiver = {}; Object.assign(receiver, { type: "js", name:"file.js" }, { type: "css" } ) console.log(receiver); // {type: "css", name: "file.js"}
//實現 deepAssign({a: {b: 1, c: 2}}, {a: {c: 3}}); //=> {a: {b: 1, c: 3}} // 只有兩個對象 function deepAssign(obj1, obj2){ for(var item in obj2){ obj1[item] = typeof obj2[item] === 'object' ? deepClone(obj1[item], obj2[item]) : obj2[item]; } return obj1; } // 通用 function deepAssign() { var args = Array.from(arguments); return args.reduce(deepClone, args[0]); function deepClone(target, obj){ if(!target) target = Array.isArray(obj) ? [] : {}; for(key in obj){ target[key] = typeof obj[key] ==="object" ? deepClone(target[key], obj[key]) : obj[key] } return target; } }
一、類數組對象:所謂類數組對象,最基本的要求就是具備length屬性的對象。
二、Array.from()方法就是將一個類數組對象或者可遍歷對象轉換成一個真正的數組。
Array.from有三個參數,Array.from(arrayLike[, mapFn[, thisArg]]),
arrayLike:想要轉換成數組的僞數組對象或可迭代對象;
mapFn:若是指定了該參數,新數組中的每一個元素會執行該回調函數;
thisArg:可選參數,執行回調函數 mapFn 時 this 對象。
該方法的返回值是一個新的數組實例(真正的數組)。
例1:Array.from ({length:n}, Fn) 將類數組轉換爲數組
Array.from({length:3}, () => 'jack') //["jack", "jack", "jack"] Array.from({length:3}, item => (item = {'name':'shao','age':18})) //[{'name':'shao','age':18}, {'name':'shao','age':18}, {'name':'shao','age':18}] Array.from({length:2}, (v, i) => item = {index:i}); //生成一個index從0到4的數組對象[{index: 0},{index: 1}]
let array = { 0: 'name', 1: 'age', 2: 'sex', 3: ['user1','user2','user3'], 'length': 4 } let arr = Array.from(array) console.log(arr) // ['name','age','sex',['user1','user2','user3']]
若是將上面代碼中length屬性去掉arr將會是一個長度爲0的空數組,若是將代碼修改一下,就是具備length屬性,可是對象的屬性名再也不是數字類型的,而是其餘字符串型的,代碼以下:
let array = { 'name': 'name', 'age': 'age', 'sex': 'sex', 'user': ['user1','user2','user3'], 'length': 4 } let arr = Array.from(array ) console.log(arr) // [ undefined, undefined, undefined, undefined ]
會發現結果是長度爲4,元素均爲undefined的數組,因而可知,要將一個類數組對象轉換爲一個真正的數組,必須具有如下條件:
(1)該類數組對象必須具備length屬性,用於指定數組的長度。若是沒有length屬性,那麼轉換後的數組是一個空數組。
(2)該類數組對象的屬性名必須爲數值型或字符串型的數字
該類數組對象的屬性名能夠加引號,也能夠不加引號
例2:Array.from (obj, mapFn)
obj指的是數組對象、相似數組對象或者是set對象,map指的是對數組中的元素進行處理的方法。
let arr = [1,1,2,5,5,6,7,8,9] let set = new Set(arr) console.log(Array.from(set)) // [1, 2, 5, 6, 7, 8, 9]
//將數組中布爾值爲false的成員指爲0 Array.from([1, ,2,3,3], x => x || 0) //[1,0,2,3,3] //將一個相似數組的對象轉爲一個數組,並在原來的基礎上乘以2倍 let arrayLike = { '0': '2', '1': '4', '2': '5', length: 3 } Array.from(arrayLike, x => x*2) //[4,8,10] //將一個set對象轉爲數組,並在原來的基礎上乘以2倍 Array.from(new Set([1,2,3,4]), x => x*2) //[2,4,6,8]
例3:Array.from(string) 將字符串轉換爲數組
Array.from('abc') //['a','b','c']
例子4——將Map解構轉爲數組,最方便的作法就是使用擴展運算符(...)
const myMap = new Map().set(true, 7) console.log(myMap); //Map(1) {true => 7} console.log([...myMap]); //[true ,7]
一、利用ES6 Set去重(ES6中最經常使用)
function unique (arr) { return Array.from(new Set(arr)) } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {}, {}]
不考慮兼容性,這種去重的方法代碼最少。這種方法沒法去掉「{}」空對象。
二、利用for嵌套for,而後splice去重(ES5中最經常使用)
function unique(arr){ for(var i=0; i<arr.length; i++){ for(var j=i+1; j<arr.length; j++){ if(arr[i]==arr[j]){ arr.splice(j,1); j--; } } } return arr; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", 15, false, undefined, NaN, NaN, "NaN", "a", {…}, {…}] //NaN和{}沒有去重,兩個null直接消失了
三、for...of + includes()
雙重for循環的升級版,外層用 for...of 語句替換 for 循環,把內層循環改成 includes()
先建立一個空數組,當 includes() 返回 false 的時候,就將該元素 push 到空數組中
相似的,還能夠用 indexOf() 來替代 includes()
function unique(arr) { var result = [] for (var i of arr) { !result.includes(i) && result.push(i) } return result } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}沒有去重
四、利用indexOf去重
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!'); return; } var array = []; for (var i = 0; i < arr.length; i++) { if (array.indexOf(arr[i]) === -1) { array.push(arr[i]); } } return array; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) // [1, "true", true, 15, false, undefined, null, NaN, NaN, "NaN", 0, "a", {…}, {…}] //NaN、{}沒有去重
五、利用sort()
function unique(arr) { if (!Array.isArray(arr)) { console.log('type error!') return; } arr = arr.sort() var arrry= [arr[0]]; for (var i = 1; i < arr.length; i++) { if (arr[i] !== arr[i-1]) { arrry.push(arr[i]); } } return arrry; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) // [0, 1, 15, "NaN", NaN, NaN, {…}, {…}, "a", false, null, true, "true", undefined] // NaN、{}沒有去重
6 、利用hasOwnProperty
function unique(arr) { var obj = {}; return arr.filter(function(item, index, arr){ return obj.hasOwnProperty(typeof item + item) ? false : (obj[typeof item + item] = true) }) } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}] //全部的都去重了
七、利用filter
function unique(arr) { return arr.filter(function(item, index, arr) { //當前元素,在原始數組中的第一個索引==當前索引值,不然返回當前元素 return arr.indexOf(item, 0) === index; }); } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)) //[1, "true", true, 15, false, undefined, null, "NaN", 0, "a", {…}, {…}]
八、利用Map數據結構去重
function arrayNonRepeatfy(arr) { let map = new Map(); let array = new Array(); // 數組用於返回結果 for (let i = 0; i < arr.length; i++) { if(map.has(arr[i])) { // 若是有該key值 map.set(arr[i], true); } else { map.set(arr[i], false); // 若是沒有該key值 array.push(arr[i]); } } return array; } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(arrayNonRepeatfy(arr)) //[1, "a", "true", true, 15, false, 1, {…}, null, NaN, NaN, "NaN", 0, "a", {…}, undefined] // {}沒去
建立一個空Map數據結構,遍歷須要去重的數組,把數組的每個元素做爲key存到Map中。因爲Map中不會出現相同的key值,因此最終獲得的就是去重後的結果。
九、利用reduce+includes
function unique(arr){ return arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev,cur],[]); } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)); // [1, "true", true, 15, false, undefined, null, NaN, "NaN", 0, "a", {…}, {…}]
十、for...of + Object
首先建立一個空對象,而後用 for 循環遍歷
利用對象的屬性不會重複這一特性,校驗數組元素是否重複
function unique(arr){ let result = [] let obj = {} for (let i of arr) { if (!obj[i]) { result.push(i) obj[i] = 1 } } return result } var arr = [1,1,'true','true',true,true,15,15,false,false, undefined,undefined, null,null, NaN, NaN,'NaN', 0, 0, 'a', 'a',{},{}]; console.log(unique(arr)); // [1, "true", 15, false, undefined, null, NaN, 0, "a", {…}]
const objArr = [{ name: '名稱1' },{ name: '名稱2' },{ name: '名稱3' },{ name: '名稱1' },{ name: '名稱2' }] const obj = {} const newObjArr = [] for(let i = 0; i < objArr.length; i++){ if(!obj[objArr[i].name]){ newObjArr.push(objArr[i]); obj[objArr[i].name] = true } } console.log(newObjArr); /*結果: [{ name: '名稱1' },{ name: '名稱2' },{ name: '名稱3' }] */
const objArr = [{ name: '名稱1' },{ name: '名稱2' },{ name: '名稱3' },{ name: '名稱1' },{ name: '名稱2' }] const obj = {} const newObjArr = objArr.reduce((prev, curr)=>{ obj[curr.name] ? true : obj[curr.name] = true && prev.push(curr); return prev }, []) console.log(newObjArr)
由於你用的fetch post修改了請求頭,致使fetch第一次發送一個options請求,詢問服務器是否支持修改的請求頭,如過服務器支持,那麼將會再次發送真正的請求。
什麼是跨域
JSONP:ajax請求受同源策略影響,不容許進行跨域請求,而script標籤src屬性中的連接卻能夠訪問跨域的js腳本,利用這個特性,服務端再也不返回JSON格式的數據,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
JSONP的缺點:
JSON只支持get,由於script標籤只能使用get請求;
JSONP須要後端配合返回指定格式的數據。
ajax與jsonp的區別
如何實現跨域
JSONP:經過動態建立script,再請求一個帶參網址實現跨域通訊。
document.domain + iframe跨域:兩個頁面都經過js強制設置document.domain爲基礎主域,就實現了同域。
location.hash + iframe跨域:a欲與b跨域相互通訊,經過中間頁c來實現。 三個頁面,不一樣域之間利用iframe的location.hash傳值,相同域之間直接js訪問來通訊。
window.name + iframe跨域:經過iframe的src屬性由外域轉向本地域,跨域數據即由iframe的window.name從外域傳遞到本地域。
postMessage跨域:能夠跨域操做的window屬性之一。
CORS:服務端設置Access-Control-Allow-Origin便可,前端無須設置,若要帶cookie請求,先後端都須要設置。
代理跨域:起一個代理服務器,實現數據的轉發
app.bundle
的大小,讓瀏覽器並行下載資源文件,提升下載速度;app.bundle
的體積,在調用某個組件時再加載對應的js文件;js原生獲取的dom是一個對象,jQuery對象就是一個數組對象,其實就是選擇出來的元素的數組集合,因此說他們二者是不一樣的對象類型不等價。
原生DOM對象轉jQuery對象:
var box = document.getElementById('box'); var $box = $(box);
jQuery對象轉原生DOM對象:
var $box = $('#box'); var box = $box[0];
區別
1.淺拷貝: 將原對象或原數組的引用直接賦給新對象,新數組,新對象/數組只是原對象的一個引用
2.深拷貝: 建立一個新的對象和數組,將原對象的各項屬性的「值」(數組的全部元素)拷貝過來,是「值」而不是「引用」
爲何要使用深拷貝?
咱們但願在改變新的數組(對象)的時候,不改變原數組(對象)
深拷貝數組
1.直接遍歷
function copyArr(arr) { let res = [] for (let i = 0; i < arr.length; i++) { res.push(arr[i]) } return res } var arr = [1,2,3,4,5] var arr2 = copyArr(arr)
2.slice()
var arr = [1,2,3,4,5] var arr2 = arr.slice()
3.concat()
var arr = [1,2,3,4,5] var arr2 = arr.concat()
深拷貝對象
1.迭代遞歸法
這是最常規的方法,思想很簡單:就是對對象進行迭代操做,對它的每一個值進行遞歸深拷貝。
function deepClone(obj){ var newObj= obj instanceof Array ? []:{}; for(var item in obj){ var temple= typeof obj[item] == 'object' ? deepClone(obj[item]):obj[item]; newObj[item] = temple; } return newObj; }
2.ES6的Object.assign(除了根屬性是深拷貝,其他都是淺拷貝)
3.ES6擴展運算符:...
「一招鮮,吃遍天」 ——序列化反序列化法
JSON.parse(JSON.stringify(XXXX))
var array = [ { number: 1 }, { number: 2 }, { number: 3 } ]; var copyArray = JSON.parse(JSON.stringify(array)) copyArray[0].number = 100; console.log(array); // [{number: 1}, { number: 2 }, { number: 3 }] console.log(copyArray); // [{number: 100}, { number: 2 }, { number: 3 }]
它也只能深拷貝對象和數組,對於其餘種類的對象,會失真。這種方法比較適合日常開發中使用,由於一般不須要考慮對象和數組以外的類型。
方式1:splice函數
arrayObject.splice(index,howmany,element1,.....,elementX)
index:必選,規定從何處添加/刪除元素。
howmany:必選,規定應該刪除多少元素。未規定此參數,則刪除從 index 開始到原數組結尾的全部元素。
element1:可選,規定要添加到數組的新元素。
<script type ="text/javascript"> var arr = [1,2,3,4]; arr.splice(0,arr.length); </script>
方式2:給數組的length賦值爲0
<script type ="text/javascript"> var arr = [1,2,3,4]; arr.length = 0; </script>
賦予數組的長度小於自己的長度,數組中後面的元素將被截斷。
賦予數組的長度大於自己的長度,將擴展數組長度,多的元素爲undefined。
方式3:直接賦予新數組 []
<script type ="text/javascript"> var arr = [1,2,3,4]; arr = []; </script>
這種方式爲將arr從新複製爲空數組,以前的數組若是沒有被引用,將等待垃圾回收。
待所有完成以後統一執行
let p1 = new Promise((resolve, reject) => { resolve('成功了') }) let p2 = new Promise((resolve, reject) => { resolve('success') }) let p3 = Promise.reject('失敗') Promise.all([p1, p2]).then((result) => { console.log(result) //['成功了', 'success'] }).catch((error) => { console.log(error) }) Promise.all([p1,p2,p3]).then((result) => { console.log(result) }).catch((error) => { console.log(error) // 失敗了,打出 '失敗' })
let wake = (time) => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(`${time / 1000}秒後醒來`) }, time) }) } let p1 = wake(3000) let p2 = wake(2000) Promise.all([p1, p2]).then((result) => { console.log(result) // [ '3秒後醒來', '2秒後醒來' ] }).catch((error) => { console.log(error) })
須要特別注意的是,Promise.all得到的成功結果的數組裏面的數據順序和Promise.all接收到的數組順序是一致的,即p1的結果在前,即使p1的結果獲取的比p2要晚。這帶來了一個絕大的好處:在前端開發請求數據的過程當中,偶爾會遇到發送多個請求並根據請求順序獲取和使用數據的場景,使用Promise.all毫無疑問能夠解決這個問題。
function promiseAll(promises) { return new Promise((resolve, reject) => { let resultCount = 0; let results = new Array(promises.length); for (let i = 0; i < promises.length; i++) { promises[i].then(value => { resultCount++; results[i] = value; if (resultCount === promises.length) { return resolve(results) } }, error => { reject(error) }) } }) } let p1 = new Promise(resolve => resolve('p1')) let p2 = new Promise(resolve => resolve('p2')) let p3 = Promise.reject('p3 error') promiseAll([p1, p2]).then(results => { console.log(results) // ['p1', 'p2'] }).catch(error => { console.log(error) }) promiseAll([p1, p2, p3]).then(results => { console.log(results) }).catch(error => { console.log(error) // 'p3 error' })
只要有一個完成就執行,返回爲最早完成的
let p1 = new Promise((resolve, reject) => { setTimeout(() => { resolve('success') },1000) }) let p2 = new Promise((resolve, reject) => { setTimeout(() => { reject('failed') }, 500) }) Promise.race([p1, p2]).then((result) => { console.log(result) }).catch((error) => { console.log(error) // 打開的是 'failed' })
var a = 100 function F1() { var b = 200 function F2() { var c = 300 console.log(a) // a是自由變量,向父級做用域尋找a,未果,再向上一級父級做用域尋找a console.log(a) // b是自由變量,向父級做用域尋找b console.log(a) } F2() } F1() // 自由變量不斷地往父級做用域去找,造成一個鏈式結構
1.核心(ECMAScript) ——提供核心語言功能
2.文檔對象模型(Dom) ——提供訪問和操做網頁內容的方法和接口
3.瀏覽器對象模型(Bom) ——提供與瀏覽器交互的方法和接口
defer=「defer」
defer屬性:代表腳本在執行時不會影響頁面的構造,也就是說,腳本會被延遲到整個頁面都解析完畢再運行
var result = 「a」 < 3; // false,由於「a」被轉化成了NaN
根據規則,任何操做數與NaN進行關係比較,結果都是false
function doadd() { if (arguments.length == 1) { alert(arguments[0] + 10); } else if (arguments.length == 2) { alert(arguments[0] + arguments[1]); } } doAdd(10) // 20 doAdd(30, 20) // 50
一、遞歸
function flatArr(arr) { var newArr = []; arr.forEach((val) => { if (Array.isArray(val)) { newArr = newArr.concat(flatArr(val)) } else { newArr.push(val) } }) return newArr; }
二、reduce
function flatArr(arr) { return arr.reduce((pre, cur) => pre.concat(Array.isArray(cur) ? flatArr(cur) : cur), []) }
3.利用數組join()或toString()方法
// join() function flatArr(arr) { arr.join().split(',') return JSON.parse(`[${arr.join()}]`) } // toString() function flatArr(arr) { arr.toString().split(',') return JSON.parse(`[${arr.toString()}]`) }
4.es6數組的flat()方法 (瀏覽器版本太低不支持)
flat方法默認打平一層嵌套,也能夠接受一個參數表示打平的層數,傳 Infinity 能夠打平任意層。
function flatArr(arr) { return arr.flat(Infinity); }
const sleep = (timeountMS) => new Promise((resolve) => { setTimeout(resolve, timeountMS); }); (async () => { console.log('11111111, ' + new Date()); await sleep(2000); console.log('22222222, ' + new Date()); await sleep(2000); console.log('33333333, ' + new Date()); })();
1.設置cookie一天後過時
function setCookie(name,expireday){ var dayobject = new Date(); // Date()函數獲取當前的日期和時間 // getTime()函數獲取的事1970年1月1號至今的毫秒數 // 注意要多加8小時,咱們位於東八區比標準時間相差8小時 var daynum = dayobject.getTime() + expireday*(24+8)*60*60*1000; // 計算過時時間毫秒數 dayobject.setTime(daynum); // 設置超時的時間 alert('name=' + name + ';' + 'expires=' + dayobject.toGMTString()); document.cookie = 'name=' + name + ';' + 'expires=' + dayobject.toGMTString(); } setCookie('coco',1)
2.設置cookie立刻過時
function delCookie(name){ var expires = new Date(); expires.setTime(expires.getTime() - 1); document.cookie = 'name='+name+';'+'expires=' + expires.toGMTString(); } // 設置cookie的過時時間是比當前時間提早一秒,也就是立馬過時了。