//值類型 let a = 200; let b = a; a = 100; console.log(a, b) // 引用類型 let a = { age: 24 }; let b = a; b.age = 25; console.log(a, b);
值類型
,值類型的複製就是複製棧裏的value
。引用類型
的複製複製的是堆的引用內存地址
。css
值類型的佔據內存比較小,引用類型佔據的內存可能會很是大,不利於複製,從CPU和性能考慮把引用類型和值類型的複製的方式給分離出來。(js引擎)html
let a;// undefined const b = "string"; const c = false; const n = 100; const s = Symbol('s');
const obj = { age: 24 }; const arr = ["1", "2", "3"]; const n = null; // 特殊的引用類型,指針指向的是空地址 // 特殊引用類型 不用於存儲數據,因此沒有拷貝,複製函數之說 function fn() { }
全部的值類型,函數 引用類型只能到Object
重點1:初始化result
重點2:使用遞歸webpack
obj1 = { name: "鬍子銀", level: "p0" }; function deepClone(obj = {}) { if (typeof obj !== 'object' || typeof obj == null) { return obj; } // 初始化返回結果 let result; if (obj instanceof Array) { result = [] } else { result = {} } // 開始拷貝 for (let key in obj) { if (obj.hasOwnProperty(key)) { // 保證key 不是原型的屬性 // 遞歸調用 result[key] = deepClone(obj[key]); } } return result; }
const a =100+10 // 110 const b = 100 +'10' // '10010' const c= true + '10' // 'true10'
100 == '100' // true 0 == '' // true 0 == false // true false =='' // true null == undefined // true
總結: 除了null
用 ==
其餘都用===
ios
truely 變量與 falsely 變量 兩次取反es6
類的繼承:extends super 重寫web
instanceof 是否是它構建的。父類。Object是全部的父類面試
Student.__proto__ === People.ProtoType // true
隱式原型 :Student.proto
顯式原型:People.ProtoTypeajax
每一個class都有顯式原型,每一個實例都有隱式原型,實例的隱式原型指向類的顯式原型。json
instanceOfaxios
this 在不一樣場景下,如何取值?
手寫bind函數
閉包在實際開發場景中的應用
變量的合法使用範圍。框裏面的均可以。
做用域:
全局做用域
函數做用域
塊級做用域 let const {}
做用域應用的特殊表現,有兩種狀況
函數
做爲參數
被傳遞。函數
做爲返回值
被返回。總之,函數定義的地方和執行的地方是不同的。
閉包:自由變量在函數定義的地方向上級做用域查找。而不是在執行的地方。
// 函數做爲返回值 function createFun() { const a = 100; return function () { console.log(100); } } const fn = createFun(); const a = 200; fn();
// 函數做爲參數被傳遞 const a = 100; function param() { console.log(a); }; function close(param) { const a = 200; param(); }; // const clo = new close(param); close(param);
函數在執行的時候決定。
箭頭函數 ==> 取的是上級做用域的值
bind call 的區別
function fn() { console.log(this); } const fnbind = fn.bind({ x: 200 },10,20,30); fn(); fn.call({ x: 100 }); fnbind()
this的使用場景,console.log(this) 一、普通函數被調用 // window 二、做爲對象方法 指向對象 三、bind,call,apply 把this的指向做爲參數傳遞進去。(傳進去的就是this) 四、箭頭函數 this指向上一層做用域 五、在class中調用
JavaScript
中的Array.prototype.slice.call(arguments)
能將有length屬性的對象轉換爲數組
Function.prototype.bind = function () { const args = Array.prototype.slice.call(arguments); // 獲取數組的第一項 const t = args.shift(); //此處this是fn1.bind()中的fn1 const self = this; return function () { return self.apply(t, args); } }
閉包: 自由變量在函數定義的地方向上級做用域查找。而不是在執行的地方。
閉包隱藏數據,只提供api,閉包中的數據,被隱藏,不被外界訪問。
建立緩存,set,get,調用get方法取到的變量是,而不是
let構成了塊級做用域
const imgUrl = "0000"; function loadImg(src) { return new Promise((resolve, reject) => { const img = document.createElement('img'); img.onload = () => { return resolve(img); } img.onerror = () => { return reject(new Error("圖片加載失敗")); } img.src = img; }) } loadImg(url).then((img) => { console.log(img.width); return img; }).then((img) => { console.log(img.height); })
事件輪訓,事件循環
js是單線程,異步要基於回調實現,event Loop就是根據異步回調的實現原理
call Stack:調用棧 用完就清空
web apis:如setTimeout dom bom等
callback queue:回調函數隊列
event loop:
總結: 同步代碼,一行一行放在Call Stack執行 遇到異步,會先「記錄」下,等待時機(定時、網絡請求等); 時機到了,就移到Callback Queue 如Call Stack爲空(即同步代碼執行完成)Event Loop開始工做 輪詢查找Callback Queue,若有則移到Call Stack 執行 而後繼續輪詢查找
dom事件也是基於Event Loop。
then 正常返回resolved ,裏面有報錯則返回rejected
catch 正常返回resolved,裏面有報錯則返回rejected
總結: 三種狀態,狀態和表現 then和catch對狀態的影響(重要) then和catch的鏈式調用(常考) 只要是沒報錯,就是resolved。
異步回調
promise也是基於回調。async-await完全消滅了回調。
- 執行async函數,返回的是Promise對象 - await至關於Promise的then (假如直接返回的數據,至關於 Promise.resolve(400)) - try...catch可捕獲異常,代替了Promise的catch
仍是基於回調函數,仍是基於event Loop
for...in(以及forEach for)是常規的同步遍歷 ????
for...of 經常使用於異步遍歷?????
宏任務與微任務
爲何微任務比宏任務的執行時間要早?
event Loop 與 DOM事件 渲染。js是單線程的。也就是說event Loop與Dom渲染共用同一個線程。
宏任務在DOM渲染後觸發,如setTimeout();
微任務,在DOM渲染後,如setTimeout();
爲何宏任務在DOM渲染後觸發,微任務在DOM渲染前觸發?
宏任務與微任務的根本區別
從event Loop解釋爲何微任務比宏任務的執行時間早。
微任務是瀏覽器規定的
宏任務是es6規定的
存放的地方不同。
總結:
JS = ECMA (ECMA262標準)+DOM(w3c) +BOM (w3c)
W3C規定web-api,css,html,網絡請求的東西還挺多的。
document object model
const div1 = document.getElementById("app1"); // const div2 = document.getElementsByClassName("appclass"); const divList = document.getElementsByTagName("div"); // list const pList = document.querySelectorAll("p"); // console.log("div1:", div1); console.log("div2", div2); console.log("divList:", divList); console.log("pList:", pList); // property 形式 修改屬性值 console.log(pList[1].style.width); console.log(pList[1]); // attribute 形式 修改屬性 pList[1].setAttribute("data-name", "imook"); console.log(pList[1].getAttribute("data-name")); pList[1].setAttribute("style", "font-size:50px");
打印出來的結果對比,直接獲取的dom節點,list的會有屬性
const listNode = document.getElementById("app1"); const flagNode = document.createElement("ul"); for (let i = 0; i <= 5; i++) { const li = document.createElement("li"); li.innerHTML = "innerHtml"; flagNode.appendChild(li); }; listNode.appendChild(flagNode);
ua
// navigator console.log(navigator.userAgent); // ua檢查方案 // screen console.log(screen.width); // location console.log(location.href); // 整個網址 console.log(location.host) // 域名 console.log(location.search); // console.log(location.hash); // 哈希 # console.log(location.pathname); // // history history.back(); history.forward();
通用的事件綁定函數
<button id="btn1">點擊</button> <script> var btn = document.getElementById("btn1"); function bindEvent(ele, type, fn) { ele.addEventListener(type, fn); }; btn.bindEvent("click", e => { // 阻止默認行爲 e.proventDefault(); // e.target console.log(e.target); console.log("事件綁定"); }) </script>
事件冒泡
事件代理
把事件綁定到父元素上,點擊子元素,彈出子元素的interhtml
代碼簡潔,減小瀏覽器的內存使用,可是不要濫用。
GET
const xhr = new XMLHttpRequest(); xhr.open("GET", "./data.json", true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log(JSON.parse(xhr.responseText)); alert(xhr.responseText); } else { console.log(xhr.responseText); } } } xhr.send(null);
POST
const xhr = new XMLHttpRequest(); xhr.open("POST", "./login", true); xhr.onreadystatechange = function () { if (xhr.readyState === 4) { if (xhr.status === 200) { console.log(JSON.parse(xhr.responseText)); alert(xhr.responseText); } else { console.log(xhr.responseText); } } } const postData = { "name": "狂徒張三" } xhr.send(JSON.stringify(postData));
301 永久重定向
302 臨時重定向
304 資源有,重複,瀏覽器用本身的。事關性能優化
404 地址錯了
403 沒有權限
jsonp的主要內容有兩點:
一、script能夠跨域
二、服務器拿到url能夠動態的返回一些內容
cors
是服務端設置請求頭,容許哪些進行訪問。
jqyery.ajax()
fetch()
axios
xmlhttprequest
題目:描述cookie localStorage sessionStorage 的區別
cookie的價值不在於本地存儲,而在於與服務端的通訊。是被借用來做爲本地存儲的工具。因爲每次請求都須要帶着cookie,因此會增長請求的數據量,並且cookie的最大的存儲空間是4kb,只能經過document.cookie來修改。過於簡陋。 修改的方式:相同的key,覆蓋,不一樣的key,追加
localStorage數據會永久存儲,除非代碼或者手動刪除 sessionStorage數據只存在於當前會話,當瀏覽器關閉就清空
常見的狀態碼:
301 永久重定向
302 臨時重定向,
舉例1:在百度檢索了一個css教程,hover上去的連接點擊之後,先是訪問百度的url而後瀏覽器的location再跳轉到真正的目的連接地址、。
舉例2:還有短鏈
304:瀏覽器已經請求過了,可使用本地的,本地的沒過時
403:沒權限
404:地址錯誤
5 **:服務端
關於協議和規範:就是一個約定和規範
get
post
get 查
post 建立新的
patch
delete
儘可能不要使用參數,使用method做爲類型
網絡請求加載比較慢,cpu計算比較快。性能優化的主要瓶頸就在於網絡請求,當部分不須要被重複請求的資源被緩存,就能夠減小http請求,從而優化性能。
哪些資源能夠被緩存?靜態資源,(js,css,圖片,與webpack打包加的hash有關,只有內容改變了,纔會再次更改)
一、強制緩存
cache-contral 強制緩存,控制強制緩存的邏輯
cache-control:max-age=2592000 (秒)
max-age:過時時間 no-cache : 本地不作緩存 no-store:本地不緩存,服務器端也不緩存。
關於Expires
二、協商緩存(對比緩存)
Last-Modified: 最後一次修改的時間
Etag: 人類的指紋,惟一的標識,字符串
二者共存,會優先使用Etag,Etag會更加精準。
總結: 就是請求服務端,問問服務端本地的能不能用。
正常操做:url的前進後退; 都有效
手動刷新:強制緩存失效,協商緩存有效
強制緩存:contral + command + 2 都失效