摘要:防抖函數分為非立即執行版和立即執行版。返回值如果有元素被刪除返回包含被刪除項目的新數組。返回值的新長度。顛倒數組中元素的順序語法參數無返回值顛倒后的新數組。如果為負值,表示倒數。停止填充位置默認為返回值返回當前數組。
77777777777777777777777777777777777777777777777777777777777777777777777777
一、html和css部分 1、如何理解CSS的盒子模型?
標準盒子模型:寬度=內容的寬度(content)+ border + padding 低版本IE盒子模型:寬度=內容寬度(content+border+padding)2、BFC?
* 什么是 BFC
BFC(Block Formatting Context)格式化上下文,是 Web 頁面中盒模型布局的 CSS 渲染模式,指一個獨立的渲染區域或者說是一個隔離的獨立容器。
* 形成 BFC 的條件
* 浮動元素,float 除 none 以外的值
* 定位元素,position(absolute,fixed)
* display 為以下其中之一的值 inline-block,table-cell,table-caption
* overflow 除了 visible 以外的值(hidden,auto,scroll)
* BFC 的特性
* 內部的 Box 會在垂直方向上一個接一個的放置。
* 垂直方向上的距離由 margin 決定
* bfc 的區域不會與 float 的元素區域重疊。
* 計算 bfc 的高度時,浮動元素也參與計算
* bfc 就是頁面上的一個獨立容器,容器里面的子元素不會影響外面元素。
3、如何清除浮動?
不清楚浮動會發生高度塌陷:浮動元素父元素高度自適應(父元素不寫高度時,子元素寫了浮動后,父元素會發生高度塌陷)
* clear清除浮動(添加空div法)在浮動元素下方添加空div,并給該元素寫css樣式: {clear:both;height:0;overflow:hidden;}
* 給浮動元素父級設置高度
* 父級同時浮動(需要給父級同級元素添加浮動)
* 父級設置成inline-block,其margin: 0 auto居中方式失效
* 給父級添加overflow:hidden 清除浮動方法
* 萬能清除法 after偽類 清浮動(現在主流方法,推薦使用)
.float_div:after{
content:".";
clear:both;
display:block;
height:0;
overflow:hidden;
visibility:hidden;
}
.float_div{
zoom:1
}
4、用純CSS創建一個三角形的原理是什么?
span {
width: 0;
height: 0;
border-top: 40px solid transparent;
border-left: 40px solid transparent;
border-right: 40px solid transparent;
border-bottom: 40px solid #ff0000;
}
5、css3實現0.5px的細線?
/* css */
.line {
position: relative;
}
.line:after {
content: "";
position: absolute;
left: 0;
top: 0;
width: 100%;
height: 1px;
background-color: #000000;
-webkit-transform: scaleY(.5);
transform: scaleY(.5);
}
/* html */
"line">
6、css實現三欄布局
左右固定,中間自適應。
flex方式
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"left">
"content">
"right">
絕對定位方式
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"left">
"content">
"right">
浮動方式
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"left">
"right">
"content">
7、讓一個div垂直居中
寬度和高度已知的
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"content">
寬度和高度未知
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"content">
flex布局
"en">
"UTF-8">
"viewport" content="width=device-width, initial-scale=1.0">
"X-UA-Compatible" content="ie=edge">
Document
"box">
"content">
二、JS
1、閉包
閉包概念
能夠讀取其他函數內部變量的函數。 或簡單理解為定義在一個函數內部的函數,內部函數持有外部函數內變量的引用。
閉包用途
1、讀取函數內部的變量 2、讓這些變量的值始終保持在內存中。不會再f1調用后被自動清除。 3、方便調用上下文的局部變量。利于代碼封裝。 原因:f1是f2的父函數,f2被賦給了一個全局變量,f2始終存在內存中,f2的存在依賴f1,因此f1也始終存在內存中,不會在調用結束后,被垃圾回收機制回收。
閉包缺點
1、由于閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。 2、閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。
閉包應用場景
閉包應用場景之setTimeout
//setTimeout傳遞的第一個函數不能帶參數
setTimeout((param) => {
alert(param)
}, 1000);
//通過閉包可以實現傳參效果
function func(param) {
return function() {
alert(param)
}
}
var f1 = func("汪某");
setTimeout(f1, 1000)//汪某
2、js中函數執行
在 ES5.1 里面函數是這樣執行的(不討論use strict和一些特殊情況,JS好復雜的),按如下順序執行:
1. 確定“this”的值 (確切的來說,this在JS里面不是一個變量名而是一個關鍵字)
2. 創建一個新的作用域
3. 處理形參/實參(沒有定義過才聲明,無論如何都重新賦值,沒有對應實參則賦值為"undefined"):
對于每一個傳入的實參,按照從左往右的順序依次執行:如果對應的形參在本作用域中還沒有定義,則在本作用域中聲明形參,并賦值。如果已經定義過了,則重新給其賦值。(沒有對應實參則賦值為"undefined")(沒有定義:就是“沒有聲明”的意思)
4. 處理函數定義(沒有定義過才聲明,無論如何都重新賦值):
對該函數中所有的定義的函數,按照代碼寫的順序依次執行:如果這個變量名在本作用域中還沒有定義,則在本作用域中聲明這個函數名,并且賦值為對應的函數,如果定義了這個變量,在可寫的情況下重新給這個變量賦值為這個函數,否則拋出異常。
5. 處理 "arguments"(沒有定義過才聲明和賦值):
如果在本作用域中沒有定義 arguments,則在本作用域中聲明arguments并給其賦值。
6. 處理變量聲明(沒有定義過才聲明,不賦值):
對于所有變量聲明,按照代碼寫的順序依次執行:如果在本作用域中沒有定義這個變量,則在本作用域中聲明這個變量,賦值為undefined
7. 然后執行函數代碼。(當然是去變量定義里面的 var 執行)
3、new一個對象的過程中發生了什么嘛
1. 創建空對象; var obj = {}; 2. 設置新對象的constructor屬性為構造函數的名稱,設置新對象的__proto__屬性指向構造函數的prototype對象; obj.__proto__ = ClassA.prototype; 3. 使用新對象調用函數,函數中的this被指向新實例對象: ClassA.call(obj);//{}.構造函數(); 4. 如果無返回值或者返回一個非對象值,則將新對象返回;如果返回值是一個新對象的話那么直接直接返回該對象。4、宏任務跟微任務
macro-task(宏任務):包括整體代碼script,setTimeout,setInterval
micro-task(微任務):Promise,process.nextTick
這一次,徹底弄懂 JavaScript 執行機制
5、防抖和節流綜合應用場景
防抖(debounce):就是指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。
search搜索聯想,用戶在不斷輸入值時,用防抖來節約請求資源。
window觸發resize的時候,不斷的調整瀏覽器窗口大小會不斷的觸發這個事件,用防抖來讓其只觸發一次
節流(throttle):就是指連續觸發事件但是在 n 秒中只執行一次函數。節流會稀釋函數的執行頻率。
鼠標不斷點擊觸發,mousedown(單位時間內只觸發一次)
監聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷 所謂防抖,就是指觸發事件后在 n 秒內函數只能執行一次,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。
防抖函數分為非立即執行版和立即執行版。
非立即執行版的意思是觸發事件后函數不會立即執行,而是在 n 秒后執行,如果在 n 秒內又觸發了事件,則會重新計算函數執行時間。
立即執行版的意思是觸發事件后函數會立即執行,然后 n 秒內不觸發事件才能繼續執行函數的效果。
/**
* @desc 函數防抖
* @param func 函數
* @param wait 延遲執行毫秒數
* @param immediate true 表立即執行,false 表非立即執行
*/
function debounce(func,wait,immediate) {
let timeout;
return function () {
let context = this;
let args = arguments;
if (timeout) clearTimeout(timeout);
if (immediate) {
var callNow = !timeout;
timeout = setTimeout(() => {
timeout = null;
}, wait)
if (callNow) func.apply(context, args)
}
else {
timeout = setTimeout(function(){
func.apply(context, args)
}, wait);
}
}
}
所謂節流,就是指連續觸發事件但是在 n 秒中只執行一次函數。 節流會稀釋函數的執行頻率。
對于節流,一般有兩種方式可以實現,分別是時間戳版和定時器版。
時間戳版的函數觸發是在時間段內開始的時候
定時器版的函數觸發是在時間段內結束的時候。
/**
* @desc 函數節流
* @param func 函數
* @param wait 延遲執行毫秒數
* @param type 1 表時間戳版,2 表定時器版
*/
function throttle(func, wait ,type) {
if(type===1){
var previous = 0;
}else if(type===2){
var timeout;
}
return function() {
let context = this;
let args = arguments;
if(type===1){
let now = Date.now();
if (now - previous > wait) {
func.apply(context, args);
previous = now;
}
}else if(type===2){
if (!timeout) {
timeout = setTimeout(() => {
timeout = null;
func.apply(context, args)
}, wait)
}
}
}
}
6、數組的常用方法
改變原數組的方法
splice() 添加/刪除數組元素
語法:arrayObject.splice(index,howmany,item1,.....,itemX) 參數: 1.index:必需。整數,規定添加/刪除項目的位置,使用負數可從數組結尾處規定位置。 2.howmany:可選。要刪除的項目數量。如果設置為 0,則不會刪除項目。 3.item1, ..., itemX: 可選。向數組添加的新項目。 返回值: 如果有元素被刪除,返回包含被刪除項目的新數組。
sort() 數組排序
語法:arrayObject.sort(sortby) 參數: 1.sortby 可選。規定排序順序。必須是函數。。 返回值: 返回包排序后的新數組。
pop() 刪除一個數組中的最后的一個元素
語法:arrayObject.pop() 參數:無 返回值: 返回被刪除的元素。
shift() 刪除數組的第一個元素
語法:arrayObject.shift() 參數:無 返回值: 返回被刪除的元素。
push() 向數組的末尾添加元素
語法:arrayObject.push(newelement1,newelement2,....,newelementX) 參數: 1.newelement1 必需。要添加到數組的第一個元素。 2.newelement2 可選。要添加到數組的第二個元素。 3.newelementX 可選。可添加若干個元素。 返回值: arrayObject 的新長度。
unshift() 向數組的開頭添加一個或更多元素
語法:arrayObject.unshift(newelement1,newelement2,....,newelementX) 參數: 1.newelement1 必需。要添加到數組的第一個元素。 2.newelement2 可選。要添加到數組的第二個元素。 3.newelementX 可選。可添加若干個元素。 返回值: arrayObject 的新長度。
reverse() 顛倒數組中元素的順序
語法:arrayObject.reverse() 參數:無 返回值: 顛倒后的新數組。
copyWithin() 指定位置的成員復制到其他位置
語法: array.copyWithin(target, start = 0, end = this.length) 參數: 1.target(必需):從該位置開始替換數據。如果為負值,表示倒數。 2.start(可選):從該位置開始讀取數據,默認為 0。如果為負值,表示倒數。 3.end(可選):到該位置前停止讀取數據,默認等于數組長度。如果為負值,表示倒數。 返回值: 返回當前數組。
fill() 填充數組
語法: array.fill(value, start, end) 參數: 1.value 必需。填充的值。 2.start 可選。開始填充位置。 3.end 可選。停止填充位置 (默認為 array.length) 返回值: 返回當前數組。
不改變原數組的方法
slice() 淺拷貝數組的元素
語法: array.slice(begin, end); 參數: 1.begin(可選): 索引數值,接受負值,從該索引處開始提取原數組中的元素,默認值為0。 2.end(可選):索引數值(不包括),接受負值,在該索引處前結束提取原數組元素,默認值為數組末尾(包括最后一個元素)。 返回值: 返回一個從開始到結束(不包括結束)選擇的數組的一部分淺拷貝到一個新數組對象,且原數組不會被修改。
join() 數組轉字符串
語法:array.join(str) 參數: 1.str(可選): 指定要使用的分隔符,默認使用逗號作為分隔符。 返回值: 返回生成的字符串。
concat() 合并兩個或多個數組
語法: var newArr =oldArray.concat(arrayX,arrayX,......,arrayX) 參數: 1.arrayX(必須):該參數可以是具體的值,也可以是數組對象。可以是任意多個。 返回值: 返回返回合并后的新數組。
indexOf() 查找數組是否存在某個元素
語法:array.indexOf(searchElement,fromIndex) 參數: 1.searchElement(必須):被查找的元素 2.fromIndex(可選):開始查找的位置(不能大于等于數組的長度,返回-1),接受負值,默認值為0。 返回值: 返回下標
lastIndexOf() 查找指定元素在數組中的最后一個位置
語法:arr.lastIndexOf(searchElement,fromIndex) 參數: 1.searchElement(必須): 被查找的元素 2.fromIndex(可選): 逆向查找開始位置,默認值數組的長度-1,即查找整個數組。 返回值: 方法返回指定元素,在數組中的最后一個的索引,如果不存在則返回 -1。(從數組后面往前查找)
includes() 查找數組是否包含某個元素
語法: array.includes(searchElement,fromIndex=0)
參數:
1.searchElement(必須):被查找的元素
2.fromIndex(可選):默認值為0,參數表示搜索的起始位置,接受負值。正值超過數組長度,數組不會被搜索,返回false。負值絕對值超過長數組度,重置從0開始搜索。
返回值: 返回布爾
7、立即執行函數
聲明一個匿名函數,馬上調用這個匿名函數。目的是保護內部變量不受污染。
(function(n1, n2) {
console.log("這是匿名函數的自執行的第一種寫法,結果為:" + (n1 + n2))
})(10, 100);
(function start(n1, n2) {
console.log("這是函數聲明方式的自執行的第一種寫法,結果為:" + (n1 + n2))
})(10, 100);
(function(n1, n2) {
console.log("這是匿名函數的自執行的第二種寫法,結果為:" + (n1 + n2))
}(10, 100));
(function start(n1, n2) {
console.log("這是函數聲明方式的自執行的第二種寫法,結果為:" + (n1 + n2))
}(10, 100));
8、js原型和原型鏈
每個對象都會在其內部初始化一個屬性,就是prototype(原型),當我們訪問一個對象的屬性時,如果這個對象內部不存在這個屬性,那么他就會去prototype里找這個屬性,這個prototype又會有自己的prototype,于是就這樣一直找下去,也就是我們平時所說的原型鏈的概念。
關系:instance.constructor.prototype = instance.proto
特點:JavaScript對象是通過引用來傳遞的,我們創建的每個新對象實體中并沒有一份屬于自己的原型副本,當我們修改原型時,與之相關的對象也會繼承這一改變。 當我們需要一個屬性時,JavaScript引擎會先看當前對象中是否有這個屬性,如果沒有的話,就會查找它的prototype對象是否有這個屬性,如此遞推下去,一致檢索到Object內建對象。
function Func(){}
Func.prototype.name = "汪某";
Func.prototype.getInfo = function() {
return this.name;
}
var person = new Func();
console.log(person.getInfo());//"汪某"
console.log(Func.prototype);//Func { name = "汪某", getInfo = function() }
參考:js原型和原型鏈
9、js中call,apply,bind參考:JavaScript中call,apply,bind方法的總結。
10、Promise一句話概括Promise:Promise對象用于異步操作,它表示一個尚未完成且預計在未來完成的異步操作。
promise是用來解決兩個問題的:
回調地獄,代碼難以維護,常常第一個的函數的輸出是第二個函數的輸入這種現象
promise可以支持多個并發的請求,獲取并發請求中的數據
這個promise可以解決異步的問題,本身不能說promise是異步的
/*Promise 的簡單實現*/
class MyPromise {
constructor(fn) {
this.resolvedCallbacks = [];
this.rejectedCallbacks = [];
this.state = "PADDING";
this.value = "";
fn(this.resolve.bind(this), this.reject.bind(this));
}
resolve(value) {
if (this.state === "PADDING") {
this.state = "RESOLVED";
this.value = value;
this.resolvedCallbacks.forEach(cb => cb());
}
}
reject(value) {
if (this.state === "PADDING") {
this.state = "REJECTED";
this.value = value;
this.rejectedCallbacks.forEach(cb => cb());
}
}
then(resolve = function() {}, reject = function() {}) {
if (this.state === "PADDING") {
this.resolvedCallbacks.push(resolve);
this.rejectedCallbacks.push(reject);
}
if (this.state === "RESOLVED") {
resolve(this.value);
}
if (this.state === "REJECTED") {
reject(this.value);
}
}
}
11、async/await
如何使用 Async 函數
async function timeout(ms) {
await new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncPrint(value, ms) {
await timeout(ms);
console.log(value);
}
asyncPrint("hello world", 50);
上面代碼指定50毫秒以后,輸出hello world。 進一步說,async函數完全可以看作多個異步操作,包裝成的一個 Promise 對象,而await命令就是內部then命令的語法糖。
待補充。。。
12、深拷貝、淺拷貝淺拷貝和深拷貝都只針對于引用數據類型,淺拷貝只復制指向某個對象的指針,而不復制對象本身,新舊對象還是共享同一塊內存;但深拷貝會另外創造一個一模一樣的對象,新對象跟原對象不共享內存,修改新對象不會改到原對象;
區別:淺拷貝只復制對象的第一層屬性、深拷貝可以對對象的屬性進行遞歸復制;
淺拷貝的實現方式
自定義函數
function simpleCopy (initalObj) {
var obj = {};
for ( var i in initalObj) {
obj[i] = initalObj[i];
}
return obj;
}
ES6 的 Object.assign()
let newObj = Object.assign({}, obj);
ES6 的對象擴展
let newObj = {...obj};
深拷貝的實現方式
JSON.stringify 和 JSON.parse
用 JSON.stringify 把對象轉換成字符串,再用 JSON.parse 把字符串轉換成新的對象。
let newObj = JSON.parse(JSON.stringify(obj));
lodash
用 lodash 函數庫提供的 _.cloneDeep 方法實現深拷貝。
var _ = require("lodash");
var newObj = _.cloneDeep(obj);
自己封裝
function deepClone(obj) {
let objClone = Array.isArray(obj) ");if (obj && typeof obj === "object") {
// for...in 會把繼承的屬性一起遍歷
for (let key in obj) {
// 判斷是不是自有屬性,而不是繼承屬性
if (obj.hasOwnProperty(key)) {
//判斷ojb子元素是否為對象或數組,如果是,遞歸復制
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = this.deepClone(obj[key]);
} else {
//如果不是,簡單復制
objClone[key] = obj[key];
}
}
}
}
return objClone;
}
13、跨域
跨域需要針對瀏覽器的同源策略來理解,同源策略指的是請求必須是同一個端口,同一個協議,同一個域名,不同源的客戶端腳本在沒有明確授權的情況下,不能讀寫對方資源。
受瀏覽器同源策略的影響,不是同源的腳本不能操作其他源下面的對象。想要操作另一個源下的對象是就需要跨域。
jsonp
iframe
跨域資源共享(CORS)
nginx 代理跨域
14、for in 和 for offor in
1.一般用于遍歷對象的可枚舉屬性。以及對象從構造函數原型中繼承的屬性。對于每個不同的屬性,語句都會被執行。
2.不建議使用for in 遍歷數組,因為輸出的順序是不固定的。
3.如果迭代的對象的變量值是null或者undefined, for in不執行循環體,建議在使用for in循環之前,先檢查該對象的值是不是null或者undefined
for of
1.for…of 語句在可迭代對象(包括 Array,Map,Set,String,TypedArray,arguments 對象等等)上創建一個迭代循環,調用自定義迭代鉤子,并為每個不同屬性的值執行語句
遍歷對象
var s = {
a: 1,
b: 2,
c: 3
}
var s1 = Object.create(s);
for (var prop in s1) {
console.log(prop); //a b c
console.log(s1[prop]); //1 2 3
}
for (let prop of s1) {
console.log(prop); //報錯如下 Uncaught TypeError: s1 is not iterable
}
for (let prop of Object.keys(s1)) {
console.log(prop); // a b c
console.log(s1[prop]); //1 2 3
}
15、如何阻止冒泡?
冒泡型事件:事件按照從最特定的事件目標到最不特定的事件目標(document對象)的順序觸發。
w3c的方法是e.stopPropagation(),IE則是使用e.cancelBubble = true。
//阻止冒泡行為
function stopBubble(e) {
//如果提供了事件對象,則這是一個非IE瀏覽器
if ( e && e.stopPropagation )
//因此它支持W3C的stopPropagation()方法
e.stopPropagation();
else
//否則,我們需要使用IE的方式來取消事件冒泡
window.event.cancelBubble = true;
}
16、如何阻止默認事件?
w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false
//阻止瀏覽器的默認行為
function stopDefault( e ) {
//阻止默認瀏覽器動作(W3C)
if ( e && e.preventDefault )
e.preventDefault();
//IE中阻止函數器默認動作的方式
else
window.event.returnValue = false;
return false;
}
17、var,let,const
//變量提升
console.log(a); // undefined
console.log(b); // 報錯
console.log(c); // 報錯
var a = 1;
let b = 2;
const c = 3;
// 全局聲明
console.log(window.a) // 1
// 重復聲明
let b = 200;//報錯
其實這里很容易理解,var是可以變量提升的。而let和const是必須聲明后才能調用的。 對于let和const來說,這里就是暫緩性死區。
18、Class
es6新增的Class其實也是語法糖,js底層其實沒有class的概念的,其實也是原型繼承的封裝。
class People {
constructor(props) {
this.props = props;
this.name = "汪某";
}
callMyName() {
console.log(this.name);
}
}
class Name extends People { // extends 其實就是繼承了哪個類
constructor(props) {
// super相當于 把類的原型拿過來
// People.call(this, props)
super(props)
}
callMyApple() {
console.log("我是汪某!")
}
}
let a = new Name("啊啊啊")
a.callMyName(); //汪某
a.callMyApple(); // 我是汪某!
19、Set
Set數據結構類似數組,但所有成員的值唯一。
let a = new Set();
[1,2,2,1,3,4,5,4,5].forEach(x=>a.add(x));
for(let k of a){
console.log(k)
};
// 1 2 3 4 5
基本使用
let a = new Set([1,2,3,3,4]);
[...a]; // [1,2,3,4]
a.size; // 4
// 數組去重
[...new Set([1,2,3,4,4,4])];// [1,2,3,4]
方法
add(value):添加某個值,返回 Set 結構本身。
delete(value):刪除某個值,返回一個布爾值,表示刪除是否成功。
has(value):返回一個布爾值,表示該值是否為Set的成員。
clear():清除所有成員,沒有返回值。
let a = new Set();
a.add(1).add(2); // a => Set(2)?{1, 2}
a.has(2); // true
a.has(3); // false
a.delete(2); // true a => Set(1)?{1}
a.clear(); // a => Set(0)?{}
20、Map
Map結構提供了“值—值”的對應,是一種更完善的 Hash 結構實現。
let a = new Map();
let b = {name: "leo" };
a.set(b,"my name"); // 添加值
a.get(b); // 獲取值
a.size; // 獲取總數
a.has(b); // 查詢是否存在
a.delete(b); // 刪除一個值
a.clear(); // 清空所有成員 無返回
基本使用
傳入數組作為參數,指定鍵值對的數組。
let a = new Map([
["name","wzx"],
["age",23]
])
如果對同一個鍵多次賦值,后面的值將覆蓋前面的值。
let a = new Map();
a.set(1,"aaa").set(1,"bbb");
a.get(1); // "bbb"
如果讀取一個未知的鍵,則返回undefined。
new Map().get("asdsad"); // undefined
同樣的值的兩個實例,在 Map 結構中被視為兩個鍵。
let a = new Map();
let a1 = ["aaa"];
let a2 = ["aaa"];
a.set(a1,111).set(a2,222);
a.get(a1); // 111
a.get(a2); // 222
方法
keys():返回鍵名的遍歷器。
values():返回鍵值的遍歷器。
entries():返回所有成員的遍歷器。
forEach():遍歷 Map 的所有成員。
let a = new Map([
["name", "leo"],
["age", 18]
])
for (let i of a.keys()) {
console.log(i)
};
//name
//age
for (let i of a.values()) {
console.log(i)
};
//leo
//18
for (let i of a.entries()) {
console.log(i)
};
//["name", "leo"]
a.forEach((v, k, m) => {
console.log(`key:${k},value:${v},map:${m}`)
})
//["age", 18]
三、手擼代碼
1、實現一個new操作符
function New(func) {
var res = {};
if (func.prototype !== null) {
res.__proto__ = func.prototype;
}
var ret = func.apply(res, Array.prototype.slice.call(arguments, 1));
if ((typeof ret === "object" || typeof ret === "function") && ret !== null) {
return;
ret;
}
return;
res;
}
var obj = New(A, 1, 2);
// equals to
var obj = new A(1, 2);
2、實現一個call或 apply
call
Function.prototype.call2 = function (context) {
var context = context || window;
context.fn = this;
var args = [];
for(var i = 1, len = arguments.length; i < len; i++) {
args.push("arguments[" + i + "]");
}
var result = eval("context.fn(" + args +")");
delete context.fn
return result;
}
apply
Function.prototype.apply2 = function (context, arr) {
var context = Object(context) || window;
context.fn = this;
var result;
if (!arr) {
result = context.fn();
}
else {
var args = [];
for (var i = 0, len = arr.length; i < len; i++) {
args.push("arr[" + i + "]");
}
result = eval("context.fn(" + args + ")")
}
delete context.fn
return result;
}
參考:JavaScript深入之call和apply的模擬實現
3、實現一個Function.bindFunction.prototype.bind2 = function (context) {
if (typeof this !== "function") {
throw new Error("Function.prototype.bind - what is trying to be bound is not callable");
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fbound = function () {
self.apply(this instanceof self ");this : context, args.concat(Array.prototype.slice.call(arguments)));
}
fNOP.prototype = this.prototype;
fbound.prototype = new fNOP();
return fbound;
}
參考:JavaScript深入之bind的模擬實現
4、實現一個繼承function Parent(name) {
this.name = name;
}
Parent.prototype.sayName = function() {
console.log("parent name:", this.name);
}
function Child(name, parentName) {
Parent.call(this, parentName);
this.name = name;
}
function create(proto) {
function F() {}
F.prototype = proto;
return new F();
}
Child.prototype = create(Parent.prototype);
Child.prototype.sayName = function() {
console.log("child name:", this.name);
}
Child.prototype.constructor = Child;
var parent = new Parent("汪某");
parent.sayName();// parent name: 汪某
var child = new Child("son", "汪某");
5、手寫一個Promise(中高級必考)
面試夠用版
function myPromise(constructor) {
let self = this;
self.status = "pending"
//定義狀態改變前的初始狀態
self.value = undefined;
//定義狀態為resolved的時候的狀態
self.reason = undefined;
//定義狀態為rejected的時候的狀態
function resolve(value) {
//兩個==="pending",保證了狀態的改變是不可逆的
if (self.status === "pending") {
self.value = value;
self.status = "resolved";
}
}
function reject(reason) {
//兩個==="pending",保證了狀態的改變是不可逆的
if (self.status === "pending") {
self.reason = reason;
self.status = "rejected";
}
}
//捕獲構造異常
try {
constructor(resolve, reject);
} catch (e) {
reject(e);
}
}
//同時,需要在 myPromise的原型上定義鏈式調用的 then方法:
myPromise.prototype.then = function(
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/7398.html
摘要:獲取的對象范圍方法獲取的是最終應用在元素上的所有屬性對象即使沒有代碼,也會把默認的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據我測試不同環境結果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續更新中……,可以關注下github 項目地址 https:...
摘要:整理收藏一些優秀的文章及大佬博客留著慢慢學習原文協作規范中文技術文檔協作規范阮一峰編程風格凹凸實驗室前端代碼規范風格指南這一次,徹底弄懂執行機制一次弄懂徹底解決此類面試問題瀏覽器與的事件循環有何區別筆試題事件循環機制異步編程理解的異步 better-learning 整理收藏一些優秀的文章及大佬博客留著慢慢學習 原文:https://www.ahwgs.cn/youxiuwenzhan...
摘要:前端工程師學習資料,快速查找面試題,經典技術文章的總結,編程技巧,幫助學習者快速定位問題花點時間整理出一下前端工程師日常工作所需要的學習資料查找,幫助學習者快速掌握前端工程師開發的基本知識編程始于足下記住再牛逼的夢想也抵不住傻逼似的堅持蝴蝶 前端工程師學習資料,快速查找面試題,經典技術文章的總結,編程技巧,幫助學習者快速定位問題花點時間整理出一下web前端工程師日常工作所需要的學習資料...
本文收集學習過程中使用到的資源。 持續更新中…… 項目地址 https://github.com/abc-club/f... 目錄 vue react react-native Weex typescript Taro nodejs 常用庫 css js es6 移動端 微信公眾號 小程序 webpack GraphQL 性能與監控 高質文章 趨勢 動效 數據結構與算法 js core 代碼規范...
閱讀 3031·2021-11-24 09:39
閱讀 2267·2021-10-08 10:05
閱讀 2758·2021-09-24 13:52
閱讀 1576·2021-09-22 15:07
閱讀 595·2019-08-30 15:55
閱讀 1813·2019-08-30 15:53
閱讀 693·2019-08-30 15:44
閱讀 3122·2019-08-30 11:20