摘要:快速排序由在年提出。如果定時器的時間到了,那么也會去下一個階段關閉的回調函數,一些準備關閉的函數等的事件輪詢機制也可以看成是單線程,由上往下執行,但是到了第階段,又會返回第一階段,死循環。
原生javaScript是中大公司挑人的核心,也是決定你未來發展高度的核心。
冒泡排序,快速排序,深度克隆,深度凍結,數組操作,本章都有。
走遍大江南北,還是原生javaScript最美
感冒給大家更新,希望大家多多點贊,謝謝!
下面是本人一些其他文章和學習的文檔 , 全棧工程師一起加油!
Node.js之快速搭建微信公眾號服務器
Node.js之快速搭建服務器+前后端數據庫session交互
ES6教程全篇
你該擁抱的TypeScript
快速排序算法"這應該是最簡單的快速排序實現,什么是快速排序呢?" "快速排序(Quicksort)是對冒泡排序的一種改進。 快速排序由C. A. R. Hoare在1962年提出。它的基本思想是: 通過一趟排序將要排序的數據分割成獨立的兩部分,其中一 部分的所有數據都比另外一部分的所有數據都要小,然后再 按此方法對這兩部分數據分別進行快速排序,整個排序過程 可以遞歸進行,以此達到整個數據變成有序序列。" function quickSort(arr) { if (arr.length <= 1) { return arr; } var left = [], right = [], baseDot = Math.round(arr.length / 2) base = arr.splice(baseDot, 1)[0]; for (var i = 0; i < arr.length; i++) { if (arr[i] < base) { left.push(arr[i]) } else { right.push(arr[i]) } } return quickSort(left).concat([base], quickSort(right)); } let arr = [5, 3, 4, 12]; const newarr = quickSort(arr); console.log(newarr); "每次遞歸調用,都會直到數組中只有一個數字為止,然后 執行上下文棧出棧,返回上一個執行上下文循環遞歸,拼接數組"冒泡排序算法
"什么是冒泡排序算法?" "冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。 它重復地走訪過要排序的元素列,依次比較兩個相鄰的元素,如果他們的順 序(如從大到小、首字母從A到Z)錯誤就把他們交換過來。走訪元素的工作 是重復地進行直到沒有相鄰元素需要交換,也就是說該元素已經排序完成。 這個算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂端 (升序或降序排列),就如同碳酸飲料中二氧化碳的氣泡最終會上浮到頂端 一樣,故名“冒泡排序”。" bubbleSortSoul1 = (arr = []) => { let count = 0; // i為輪數(因i從0開始 即i深度克隆arr[j]? 如果有這種特殊癖好 那么j就從1開始吧,然后j arr[j + 1]) { let temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } console.log(`bubbleSortSoul1排序完成用了${count}輪`); return arr; }
"為什么我們需要深度克隆?而且面試必問?"
"因為引用數據類型存儲在堆空間中,當兩個變量同時指向同一個地址時, 只要一個改變,那么另外一個也會跟著變,我們的原意是想一個改變,另 一個不變,那么就需要重新開拓一個堆空間出來,所以就有了深度克隆。" "第一種方法(只適用于基礎類型)" const newObj = JSON.parse(JSON.stringify(oldObj)); "第二種方法,涵蓋所有的類型" const getType = (obj)=> { var toString = Object.prototype.toString; var map = { "[object Boolean]" : "boolean", "[object Number]" : "number", "[object String]" : "string", "[object Function]" : "function", "[object Array]" : "array", "[object Date]" : "date", "[object RegExp]" : "regExp", "[object Undefined]": "undefined", "[object Null]" : "null", "[object Object]" : "object", "[object Symbol]" : "symbol" }; if(obj instanceof Element) {//因為對不同標簽,toString會返回對應不同標簽的構造函數 return "element"; } return map[toString.call(obj)]; } const getRegExp = re => { var flags = ""; if (re.global) flags += "g"; if (re.ignoreCase) flags += "i"; if (re.multiline) flags += "m"; return flags; }; /** * deep clone * @param {[type]} parent object 需要進行克隆的對象 * @return {[type]} 深克隆后的對象 */ const deepClone = oldObj => { // 維護兩個儲存循環引用的數組 const oldObjArr = []; const newObjArr = []; const clone = oldObj => { let newObj, proto; const type = getType(oldObj); switch(type){ case "boolean": case "number": case "string": case "null": case "undefined": case "function":{ return oldObj; break; } case "symbol":{ return Symbol(Symbol.keyFor(oldObj).toString()); break; } case "array":{ newObj = []; break; } case "regExp":{ newObj = new RegExp(oldObj.source, getRegExp(oldObj)); if (oldObj.lastIndex) newObj.lastIndex = oldObj.lastIndex; break; } case "date":{ newObj = new Date(oldObj.getTime()); break; } //case "obj": default:{ // 處理對象原型 proto = Object.getPrototypeOf(oldObj); // 利用Object.create切斷原型鏈 newObj = Object.create(proto); break; } } // 處理循環引用 const index = oldObjArr.indexOf(oldObj); if (index != -1) {// 如果父數組存在本對象,說明之前已經被引用過,直接返回此對象 return newObjArr[index]; } oldObjArr.push(oldObj); newObjArr.push(newObj); /*數組和對象都可以用forin語句,雖然數組使用forin會有一個問題(具體看最下面)。 但是這里不會影響,所以這么用 */ for (let i in oldObj) {// 遞歸 newObj[i] = clone(oldObj[i]); } return newObj; }; return clone(oldObj); } /* 測試成功 */ function person(pname) { this.name = pname; } const Messi = new person("Messi"); function say() { console.log("hi"); }; const oldObj = { a: say, b: new Array(1), c: new RegExp("ab+c", "i"), d: Messi }; const newObj = deepClone(oldObj); console.log(newObj.a, oldObj.a); //[Function: say] [Function: say] console.log(newObj.b[0], oldObj.b[0]); // undefined undefined console.log(newObj.c, oldObj.c); // /ab+c/i /ab+c/i console.log(newObj.d.constructor, oldObj.d.constructor); // [Function: person][Function: person] "所有的類型都可以被克隆,完美版"
判斷對象是否一個數組的條件是:
Array.isArray(),這個在安卓的瀏覽器中兼容性一般
arr instanceof Array 這個兼容性不錯,可以使用
還有就是arr. _proto_ .consturctor == Array 這個也是可以的 兼容性應該還不錯
Object.prototype.tostring.call(arr) == [object Array] 這個也可以
如何提取用最原生的方法提取一個對象內部所有屬性的值,并且放在不同數組中?個人認為第一題和第二題結合起來,可以用來處理前后臺交互的數據,如果格式很復雜,也可以使用這兩者的模式結合,然后把他們分別提取出來進行操作。
const obj = { name: "json", age: 1, friend: "夢露", info: { name: "Aron", age: 2, friend: "杰西卡", info: { name: "rose", age: 3, friend: "霉霉", info: { name: "jerry", age: 4, friend: "比伯", info: { name: "damu", age: 5, friend: "XJ", }, }, }, } } let namearr, agearr, friendarr; namearr = []; agearr = []; friendarr = []; check(obj); function check(obj) { const items = Object.getOwnPropertyNames(obj) items.forEach(function (item) { if (Object.prototype.toString.call(obj[item]) == "[object Object]") { check(obj[item]); } else { if (item.toString() === "name") { namearr.push(obj[item]) } else if (item.toString() === "age") { agearr.push(obj[item]) } else if (item.toString() === "friend") { friendarr.push(obj[item]) } } }) } /* 這種方法也是一樣的效果 使用for in循環代替的Object.getOwnPropertyNames(obj)方法 function check(obj) { for (var item in obj) { if (Object.prototype.toString.call(obj[item]) == "[object Object]") { check(obj[item]); } else { if (item == "name") { namearr.push(obj[item]) } else if (item == "age") { agearr.push(obj[item]) } else if (item == "friend") { friendarr.push(obj[item]) } } } }*/ console.log(`namearr:${namearr}`) console.log(`agearr:${agearr}`) console.log(`friendarr:${friendarr}`)請手寫一個數組由小到大排序而且去重,不得使用高階函數
let arr = [1, 1, 2, 2, 5, 5, "a", "a", "3", "3"] arr = arr.sort(); let realarr = []; for (let i = 0; i < arr.length; i++) { if (i == 0) { realarr.push(arr[i]) } else if (i !== 0 && arr[i] !== arr[i - 1]) { realarr.push(arr[i]) } } console.log(realarr)
### 如何將一個對象深度凍結?
跟上面的數組面試題一樣,利用了執行上下文棧,先進的后出,最先凍結最深層里面的那個屬性, 再依次返回上一層繼續凍結 var obj = { name:"王寶強", age:18, wife:{ name:"陳羽凡", age:17, son:{ name:"賈乃亮", age:48, girlFriend:{ name:"吳秀波", age:50, zuo:function () { console.log("翻舊賬") }, foods:["棉花糖","粉色的棉花糖","各種棉花糖",{a:"a"}] } } } }; Object.prototype.deepFreeze = function () { var keys = Object.getOwnPropertyNames(this); var that = this; keys.forEach(function (key) { var val = that[key]; if(Object.prototype.toString.call(val) === "[object Object]" || Object.prototype.toString.call(val) === "[object Array]"){ val.deepFreeze() } }); return Object.freeze(this) } obj.deepFreeze()
## 請使用定時器和canvas寫一個隨機生成多個彩色泡
請自己定義一個DOM節點的R操作,以此作為queryselector在IE8以下的polifill。Document
(function(w){ w.app = {}; w.app.getElementByClassName=function(className){ var allnode=document.getElementsByTagName("*"); console.log(allnode) var arr=[]; for(var i=0;i請你手寫一個ajax原生javaScript請求? "由于ajax一般用于比較舊的技術,這里不適用ES6語法" var xhr = new XMLHttpRuest(); xhr.onreadystatechange = function () { if (xhr.readyState == 0) { //xhr對象創建好了 初始化狀態 console.log(0) } if (xhr.readyState == 1) { //代表xhr.send方法還未調用(還未發送請求),還可以設置請求頭相關信息 console.log(1) } if (xhr.readyState == 2) { //此時send方法被調用了 響應頭和首行已經回來了 console.log(xhr.getResponseHeader("etag")) console.log(2) } if (xhr.readyState == 3) { console.log(3) } if (xhr.readyState === 4 && xhr.status === 200) { console.log(4) console.log(xhr.responseText); } } xhr.open("GET", "http://localhost:3000/ajax?username=123&password=456"); // xhr.setRequestHeader("content-type", "application/x-www-form-urlencoded"); // xhr.send("username=123&password=456"); xhr.send() }*/ "http://上面是原生的ajax寫法,下面是jQuery中的兩種ajax寫法" " 1. 原生jQuery寫法 " $("#btn").click(function () { $.ajax({ url: "http://localhost:3000/ajax", data: "username=jack&password=123", method: "POST", success: function (data) { console.log(data) }, error: function (error) { console.log(error) } }) "2.簡寫" $.post("http://localhost:3000/ajax", "username=rose&age=12", (data) => { console.log(data) }) "http://如果是get請求直接上面改成get就可以了,data是服務器響應回來的數據"然后這邊給一下服務器 Node.js的express代碼 響應上面的ajax請求的const express = require("express"); const app = express(); app.use(express.static("public")) app.use(express.urlencoded({ extended: true })); app.get("/ajax", (req, res) => { console.log(req.query) res.send("這是ajax的get請求") }) app.post("/ajax", (req, res) => { res.send("這是ajax的post請求") console.log(req.body) }) app.listen(3000, err => { if (!err) { console.log("端口監聽成功"); } else { console.log("端口監聽失敗" + err); } })如何使用原生javaScript方法提取一個多重對象的值,并且塞到不同對應的數組中?"這里使用了遞歸,還有Object原型上的方法,執行上下文棧先進后出的知識。" const obj = { name: "json", age: 1, friend: "夢露", info: { name: "Aron", age: 2, friend: "杰西卡", info: { name: "rose", age: 3, friend: "霉霉", info: { name: "jerry", age: 4, friend: "比伯", info: { name: "damu", age: 5, friend: "XJ", }, }, }, } } let namearr, agearr, friendarr; namearr = []; agearr = []; friendarr = []; check(obj); /* function check(obj) { const items = Object.getOwnPropertyNames(obj) items.forEach(function (item) { if (Object.prototype.toString.call(obj[item]) == "[object Object]") { check(obj[item]); } else { if (item.toString() === "name") { namearr.push(obj[item]) } else if (item.toString() === "age") { agearr.push(obj[item]) } else if (item.toString() === "friend") { friendarr.push(obj[item]) } } }) }*/ function check(obj) { for (var item in obj) { if (Object.prototype.toString.call(obj[item]) == "[object Object]") { check(obj[item]); } else { if (item == "name") { namearr.push(obj[item]) } else if (item == "age") { agearr.push(obj[item]) } else if (item == "friend") { friendarr.push(obj[item]) } } } } console.log(`namearr:${namearr}`) console.log(`namearr:${agearr}`) console.log(`namearr:${friendarr}`)## 請手寫一個jsonp和cors 解決跨域問題的代碼 ?
"jsonp" document.getElementById("btn").onclick = function () { /* 1. jsonp - 特點: 1. 利用script標簽天然跨域跨域的特性解決跨域的, 民間推出的 2. 兼容性極好 */ //創建一個script標簽 const script = document.createElement("script"); //設置了響應成功的回調函數 window.jsoncallback = function (data) { console.log(data); } //設置script的src屬性, 向指定服務器發送請求 script.src = "http://localhost:3000/?callback=jsoncallback"; //添加到body中生效 document.body.appendChild(script); } ------ "cors的解決方法:在Node.js的服務器代碼中設置一個響應頭" app.get("/cors", (req, res) => { /* 1. cors 特點: - 官方推出解決跨域的方案,使用起來及其簡單,只需在服務器設置一個響應頭 - 兼容性較差 */ //設置響應頭 res.set("access-control-allow-origin", "*"); //允許所有網址跨域瀏覽器的輪詢機制請簡述"1.瀏覽器的事件輪詢機制 瀏覽器中對于js依靠js引擎實現,js引擎是單線程,不像java,php這些可以是多線程,高并發。如果要說到瀏覽器的輪詢機制,那么我們首先要說的 就是單線程的js引擎,前端的核心編程思維模式是異步編程,無論是頁面效果、前后端的數據交互,都是以異步為核心,每個需要異步的場景, 往往伴隨著回調函數去執行,而單線程的JS引擎是無法自身做這么多工作,還需要異步線程。 1.每當JS引擎解析代碼時遇到異步代碼時,交給異步線程,繼續往下解析代碼。 2.異步線程處理這些異步代碼時,一旦他們的所對應的回調函數達到執行條件便會塞進異步隊列中,等待JS引擎的輪詢。 3.JS引擎會在解析完下面的所有代碼后,再去輪詢異步隊列,從左到右,依次執行,這也是說為什么定時器的時間不準確的原因,在JS 解析代碼時,如果遇到下面代碼特別多的時候,那么它就沒時間去輪詢異步隊列的代碼。 瀏覽器中的輪詢機制有一個特殊的 requestAnimationFrame(callbackname),它所對應的回調函數,是在瀏覽器下一次重繪重排時執行,它是一個宏任務,有待考證 ,目前看只要觸發重繪重排就會調用回調函數,可以避免掉幀,優化性能,減少重繪重排次數,即使一個空白頁面,它也會重繪重排,所以只要運用好, 它是完全可以替代定時器,還可以使用cancelAnimationFrame(callbackname)清除。 "Node.js中的事件輪詢機制 Event loop"Node.js的事件輪詢機制外還有同步代碼,微任務, 要想徹底弄懂Node的代碼執行,得結合下面的微任 務一起學習。" "1.執行已經到時間的setTimeout 和 setInterval 2.執行延遲到一個循環迭代的i/o回調 3.系統內部的 idle prepare等 4.poll 輪詢回調隊列,依次取出,同步執行,與JS的異步隊列執行有點相像 直到回調隊列為空 或者系統奔潰了 如果回調隊列沒有內容,那么看 之前是否設置過setImmadiate(),如果有就去下一個階段,如果沒有,就在當前等待新的回調函數。 如果定時器的時間到了,那么也會去下一個階段 5. setImmediate 6.關閉的回調函數 ,一些準備關閉的函數等. Node.js的事件輪詢機制也可以看成是單線程,由上往下執行,但是到了第6階段,又會返回第一階段,死循環。 "什么是微任務什么是宏任務?"想得太多反而不好,把每個宏任務看成銀行排隊的老大爺,把微任務看成老大爺需要的業務, 可能他需要辦存款,理財,買紀念幣等,柜臺人員不幫老大爺辦完 他所需要的任務 -- 微任務,就不會切換到下一個老大爺 -- 宏任務, 但是編程的邏輯不 能完全抽象成現實生活, 照這種說法,只能先有老大爺才會有業務需要, ??墒窃贜ode中,先執行的是微任務,只有微任務如果有多層,先執行最頂層,再往下依次執 行)執行完后才能去執行宏任務,微任務有兩種,一種是process.nextTick() 中的函數,一種是Promise.then()中的函數,只有他們執行完后,才會去執行宏任務:setTim eout ,setIneterval,setImmadie。(即執行完了微任務才會遵循Node.js的輪詢機制去執行, 一切微任務優先)"
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/53879.html
摘要:在他的重學前端課程中提到到現在為止,前端工程師已經成為研發體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎前端工程師吃飯的家伙,深度廣度一樣都不能差。 開篇 前端開發是一個非常特殊的行業,它的歷史實際上不是很長,但是知識之繁雜,技術迭代速度之快是其他技術所不能比擬的。 winter在他的《重學前端》課程中提到: 到現在為止,前端工程師已經成為研...
摘要:在他的重學前端課程中提到到現在為止,前端工程師已經成為研發體系中的重要崗位之一。大部分前端工程師的知識,其實都是來自于實踐和工作中零散的學習。一基礎前端工程師吃飯的家伙,深度廣度一樣都不能差。開篇 前端開發是一個非常特殊的行業,它的歷史實際上不是很長,但是知識之繁雜,技術迭代速度之快是其他技術所不能比擬的。 winter在他的《重學前端》課程中提到: 到現在為止,前端工程師已經成為研發體系...
摘要:我從沒有聽到有人問如何做一名優秀甚至卓越的前端工程師。作為一個優秀的前端工程師還需要深入了解以及學會處理的這些缺陷。再者,優秀的前端工程師需要具備良好的溝通能力,因為前端工程師至少都要滿足四類客戶的需求。 我所遇到的前端程序員分兩種: 第一種一直在問:如何學習前端? 第二種總說:前端很簡單,就那么一點東西。 我從沒有聽到有人問:如何做一名優秀、甚至卓越的WEB前端工程師...
摘要:我從沒有聽到有人問如何做一名優秀甚至卓越的前端工程師。作為一個優秀的前端工程師還需要深入了解以及學會處理的這些缺陷。再者,優秀的前端工程師需要具備良好的溝通能力,因為前端工程師至少都要滿足四類客戶的需求。 我所遇到的前端程序員分兩種: 第一種一直在問:如何學習前端? 第二種總說:前端很簡單,就那么一點東西。 我從沒有聽到有人問:如何做一名優秀、甚至卓越的WEB前端工程師...
摘要:我從沒有聽到有人問如何做一名優秀甚至卓越的前端工程師。作為一個優秀的前端工程師還需要深入了解以及學會處理的這些缺陷。再者,優秀的前端工程師需要具備良好的溝通能力,因為前端工程師至少都要滿足四類客戶的需求。 我所遇到的前端程序員分兩種: 第一種一直在問:如何學習前端? 第二種總說:前端很簡單,就那么一點東西。 我從沒有聽到有人問:如何做一名優秀、甚至卓越的WEB前端工程師...
閱讀 1620·2019-08-29 13:53
閱讀 3218·2019-08-29 13:50
閱讀 862·2019-08-27 10:51
閱讀 573·2019-08-26 18:36
閱讀 1820·2019-08-26 11:00
閱讀 613·2019-08-26 10:36
閱讀 3224·2019-08-23 17:58
閱讀 2038·2019-08-23 15:17