成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

2019前端基礎(chǔ)面試秘籍(更新于5.13)

levy9527 / 3317人閱讀

摘要:防抖函數(shù)分為非立即執(zhí)行版和立即執(zhí)行版。返回值如果有元素被刪除返回包含被刪除項目的新數(shù)組。返回值的新長度。顛倒數(shù)組中元素的順序語法參數(shù)無返回值顛倒后的新數(shù)組。如果為負(fù)值,表示倒數(shù)。停止填充位置默認(rèn)為返回值返回當(dāng)前數(shù)組。

77777777777777777777777777777777777777777777777777777777777777777777777777

一、html和css部分 1、如何理解CSS的盒子模型?

標(biāo)準(zhǔn)盒子模型:寬度=內(nèi)容的寬度(content)+ border + padding

低版本IE盒子模型:寬度=內(nèi)容寬度(content+border+padding)
2、BFC?
* 什么是 BFC

   BFC(Block Formatting Context)格式化上下文,是 Web 頁面中盒模型布局的 CSS 渲染模式,指一個獨立的渲染區(qū)域或者說是一個隔離的獨立容器。
* 形成 BFC 的條件

   * 浮動元素,float 除 none 以外的值
   * 定位元素,position(absolute,fixed)
   * display 為以下其中之一的值 inline-block,table-cell,table-caption
   * overflow 除了 visible 以外的值(hidden,auto,scroll)
* BFC 的特性
   * 內(nèi)部的 Box 會在垂直方向上一個接一個的放置。
   * 垂直方向上的距離由 margin 決定
   * bfc 的區(qū)域不會與 float 的元素區(qū)域重疊。
   * 計算 bfc 的高度時,浮動元素也參與計算
   * bfc 就是頁面上的一個獨立容器,容器里面的子元素不會影響外面元素。
3、如何清除浮動?
不清楚浮動會發(fā)生高度塌陷:浮動元素父元素高度自適應(yīng)(父元素不寫高度時,子元素寫了浮動后,父元素會發(fā)生高度塌陷)
* clear清除浮動(添加空div法)在浮動元素下方添加空div,并給該元素寫css樣式:   {clear:both;height:0;overflow:hidden;}
* 給浮動元素父級設(shè)置高度
* 父級同時浮動(需要給父級同級元素添加浮動)
* 父級設(shè)置成inline-block,其margin: 0 auto居中方式失效
* 給父級添加overflow:hidden 清除浮動方法
* 萬能清除法 after偽類 清浮動(現(xiàn)在主流方法,推薦使用)

.float_div:after{
	content:".";
	clear:both;
	display:block;
	height:0;
	overflow:hidden;
	visibility:hidden;
}
.float_div{
	zoom:1
} 
4、用純CSS創(chuàng)建一個三角形的原理是什么?
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實現(xiàn)0.5px的細(xì)線?

/* 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實現(xiàn)三欄布局

左右固定,中間自適應(yīng)。

    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、閉包

閉包概念

能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
或簡單理解為定義在一個函數(shù)內(nèi)部的函數(shù),內(nèi)部函數(shù)持有外部函數(shù)內(nèi)變量的引用。

閉包用途

1、讀取函數(shù)內(nèi)部的變量
2、讓這些變量的值始終保持在內(nèi)存中。不會再f1調(diào)用后被自動清除。
3、方便調(diào)用上下文的局部變量。利于代碼封裝。
原因:f1是f2的父函數(shù),f2被賦給了一個全局變量,f2始終存在內(nèi)存中,f2的存在依賴f1,因此f1也始終存在內(nèi)存中,不會在調(diào)用結(jié)束后,被垃圾回收機制回收。

閉包缺點

1、由于閉包會使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
2、閉包會在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。

閉包應(yīng)用場景

閉包應(yīng)用場景之setTimeout

//setTimeout傳遞的第一個函數(shù)不能帶參數(shù)
setTimeout((param) => {
    alert(param)
}, 1000);


//通過閉包可以實現(xiàn)傳參效果
function func(param) {
    return function() {
        alert(param)
    }
}
var f1 = func("汪某");
setTimeout(f1, 1000)//汪某
2、js中函數(shù)執(zhí)行

在 ES5.1 里面函數(shù)是這樣執(zhí)行的(不討論use strict和一些特殊情況,JS好復(fù)雜的),按如下順序執(zhí)行:

1. 確定“this”的值 (確切的來說,this在JS里面不是一個變量名而是一個關(guān)鍵字)
2. 創(chuàng)建一個新的作用域
3. 處理形參/實參(沒有定義過才聲明,無論如何都重新賦值,沒有對應(yīng)實參則賦值為"undefined"): 
對于每一個傳入的實參,按照從左往右的順序依次執(zhí)行:如果對應(yīng)的形參在本作用域中還沒有定義,則在本作用域中聲明形參,并賦值。如果已經(jīng)定義過了,則重新給其賦值。(沒有對應(yīng)實參則賦值為"undefined")(沒有定義:就是“沒有聲明”的意思)
4. 處理函數(shù)定義(沒有定義過才聲明,無論如何都重新賦值): 
對該函數(shù)中所有的定義的函數(shù),按照代碼寫的順序依次執(zhí)行:如果這個變量名在本作用域中還沒有定義,則在本作用域中聲明這個函數(shù)名,并且賦值為對應(yīng)的函數(shù),如果定義了這個變量,在可寫的情況下重新給這個變量賦值為這個函數(shù),否則拋出異常。
5. 處理 "arguments"(沒有定義過才聲明和賦值): 
如果在本作用域中沒有定義 arguments,則在本作用域中聲明arguments并給其賦值。
6. 處理變量聲明(沒有定義過才聲明,不賦值):
對于所有變量聲明,按照代碼寫的順序依次執(zhí)行:如果在本作用域中沒有定義這個變量,則在本作用域中聲明這個變量,賦值為undefined
7. 然后執(zhí)行函數(shù)代碼。(當(dāng)然是去變量定義里面的 var 執(zhí)行)
3、new一個對象的過程中發(fā)生了什么嘛
1. 創(chuàng)建空對象;
var obj = {};
2. 設(shè)置新對象的constructor屬性為構(gòu)造函數(shù)的名稱,設(shè)置新對象的__proto__屬性指向構(gòu)造函數(shù)的prototype對象;
obj.__proto__ = ClassA.prototype;
3. 使用新對象調(diào)用函數(shù),函數(shù)中的this被指向新實例對象:
ClassA.call(obj);//{}.構(gòu)造函數(shù)();          
4. 如果無返回值或者返回一個非對象值,則將新對象返回;如果返回值是一個新對象的話那么直接直接返回該對象。
4、宏任務(wù)跟微任務(wù)

macro-task(宏任務(wù)):包括整體代碼script,setTimeout,setInterval

micro-task(微任務(wù)):Promise,process.nextTick

這一次,徹底弄懂 JavaScript 執(zhí)行機制

5、防抖和節(jié)流

綜合應(yīng)用場景

防抖(debounce):就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果在 n 秒內(nèi)又觸發(fā)了事件,則會重新計算函數(shù)執(zhí)行時間。

search搜索聯(lián)想,用戶在不斷輸入值時,用防抖來節(jié)約請求資源。

window觸發(fā)resize的時候,不斷的調(diào)整瀏覽器窗口大小會不斷的觸發(fā)這個事件,用防抖來讓其只觸發(fā)一次

節(jié)流(throttle):就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)。節(jié)流會稀釋函數(shù)的執(zhí)行頻率。

鼠標(biāo)不斷點擊觸發(fā),mousedown(單位時間內(nèi)只觸發(fā)一次)

監(jiān)聽滾動事件,比如是否滑到底部自動加載更多,用throttle來判斷 所謂防抖,就是指觸發(fā)事件后在 n 秒內(nèi)函數(shù)只能執(zhí)行一次,如果在 n 秒內(nèi)又觸發(fā)了事件,則會重新計算函數(shù)執(zhí)行時間。

防抖函數(shù)分為非立即執(zhí)行版和立即執(zhí)行版。

非立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)不會立即執(zhí)行,而是在 n 秒后執(zhí)行,如果在 n 秒內(nèi)又觸發(fā)了事件,則會重新計算函數(shù)執(zhí)行時間。

立即執(zhí)行版的意思是觸發(fā)事件后函數(shù)會立即執(zhí)行,然后 n 秒內(nèi)不觸發(fā)事件才能繼續(xù)執(zhí)行函數(shù)的效果。

/**
 * @desc 函數(shù)防抖
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @param immediate true 表立即執(zhí)行,false 表非立即執(zhí)行
 */
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);
        }
    }
}

所謂節(jié)流,就是指連續(xù)觸發(fā)事件但是在 n 秒中只執(zhí)行一次函數(shù)。 節(jié)流會稀釋函數(shù)的執(zhí)行頻率。

對于節(jié)流,一般有兩種方式可以實現(xiàn),分別是時間戳版和定時器版。

時間戳版的函數(shù)觸發(fā)是在時間段內(nèi)開始的時候

定時器版的函數(shù)觸發(fā)是在時間段內(nèi)結(jié)束的時候。

/**
 * @desc 函數(shù)節(jié)流
 * @param func 函數(shù)
 * @param wait 延遲執(zhí)行毫秒數(shù)
 * @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、數(shù)組的常用方法

改變原數(shù)組的方法

splice() 添加/刪除數(shù)組元素

語法:arrayObject.splice(index,howmany,item1,.....,itemX)
參數(shù):
   1.index:必需。整數(shù),規(guī)定添加/刪除項目的位置,使用負(fù)數(shù)可從數(shù)組結(jié)尾處規(guī)定位置。
   2.howmany:可選。要刪除的項目數(shù)量。如果設(shè)置為 0,則不會刪除項目。
   3.item1, ..., itemX: 可選。向數(shù)組添加的新項目。

返回值: 如果有元素被刪除,返回包含被刪除項目的新數(shù)組。

sort() 數(shù)組排序

語法:arrayObject.sort(sortby)
參數(shù):
   1.sortby	可選。規(guī)定排序順序。必須是函數(shù)。。

返回值: 返回包排序后的新數(shù)組。

pop() 刪除一個數(shù)組中的最后的一個元素

語法:arrayObject.pop()
參數(shù):無

返回值: 返回被刪除的元素。

shift() 刪除數(shù)組的第一個元素

語法:arrayObject.shift()
參數(shù):無

返回值: 返回被刪除的元素。

push() 向數(shù)組的末尾添加元素

語法:arrayObject.push(newelement1,newelement2,....,newelementX)
參數(shù):
   1.newelement1	必需。要添加到數(shù)組的第一個元素。
   2.newelement2	可選。要添加到數(shù)組的第二個元素。
   3.newelementX	可選??商砑尤舾蓚€元素。

返回值: arrayObject 的新長度。

unshift() 向數(shù)組的開頭添加一個或更多元素

語法:arrayObject.unshift(newelement1,newelement2,....,newelementX)
參數(shù):
   1.newelement1	必需。要添加到數(shù)組的第一個元素。
   2.newelement2	可選。要添加到數(shù)組的第二個元素。
   3.newelementX	可選??商砑尤舾蓚€元素。

返回值: arrayObject 的新長度。

reverse() 顛倒數(shù)組中元素的順序

語法:arrayObject.reverse()
參數(shù):無

返回值: 顛倒后的新數(shù)組。

copyWithin() 指定位置的成員復(fù)制到其他位置

語法: array.copyWithin(target, start = 0, end = this.length)
參數(shù):
   1.target(必需):從該位置開始替換數(shù)據(jù)。如果為負(fù)值,表示倒數(shù)。
   2.start(可選):從該位置開始讀取數(shù)據(jù),默認(rèn)為 0。如果為負(fù)值,表示倒數(shù)。
   3.end(可選):到該位置前停止讀取數(shù)據(jù),默認(rèn)等于數(shù)組長度。如果為負(fù)值,表示倒數(shù)。

返回值: 返回當(dāng)前數(shù)組。

fill() 填充數(shù)組

語法: array.fill(value, start, end)
參數(shù):
   1.value	必需。填充的值。
   2.start	可選。開始填充位置。
   3.end	可選。停止填充位置 (默認(rèn)為 array.length)

返回值: 返回當(dāng)前數(shù)組。

不改變原數(shù)組的方法

slice() 淺拷貝數(shù)組的元素

語法: array.slice(begin, end);
參數(shù):
   1.begin(可選): 索引數(shù)值,接受負(fù)值,從該索引處開始提取原數(shù)組中的元素,默認(rèn)值為0。
   2.end(可選):索引數(shù)值(不包括),接受負(fù)值,在該索引處前結(jié)束提取原數(shù)組元素,默認(rèn)值為數(shù)組末尾(包括最后一個元素)。

返回值: 返回一個從開始到結(jié)束(不包括結(jié)束)選擇的數(shù)組的一部分淺拷貝到一個新數(shù)組對象,且原數(shù)組不會被修改。

join() 數(shù)組轉(zhuǎn)字符串

語法:array.join(str)
參數(shù):
   1.str(可選): 指定要使用的分隔符,默認(rèn)使用逗號作為分隔符。

返回值: 返回生成的字符串。

concat() 合并兩個或多個數(shù)組

語法: var newArr =oldArray.concat(arrayX,arrayX,......,arrayX)
參數(shù):
   1.arrayX(必須):該參數(shù)可以是具體的值,也可以是數(shù)組對象??梢允侨我舛鄠€。

返回值: 返回返回合并后的新數(shù)組。

indexOf() 查找數(shù)組是否存在某個元素

語法:array.indexOf(searchElement,fromIndex)
參數(shù):
   1.searchElement(必須):被查找的元素
   2.fromIndex(可選):開始查找的位置(不能大于等于數(shù)組的長度,返回-1),接受負(fù)值,默認(rèn)值為0。

返回值: 返回下標(biāo)

lastIndexOf() 查找指定元素在數(shù)組中的最后一個位置

語法:arr.lastIndexOf(searchElement,fromIndex)
參數(shù):
   1.searchElement(必須): 被查找的元素
   2.fromIndex(可選): 逆向查找開始位置,默認(rèn)值數(shù)組的長度-1,即查找整個數(shù)組。

返回值: 方法返回指定元素,在數(shù)組中的最后一個的索引,如果不存在則返回 -1。(從數(shù)組后面往前查找)

includes() 查找數(shù)組是否包含某個元素

語法: array.includes(searchElement,fromIndex=0)
參數(shù):
   1.searchElement(必須):被查找的元素
   2.fromIndex(可選):默認(rèn)值為0,參數(shù)表示搜索的起始位置,接受負(fù)值。正值超過數(shù)組長度,數(shù)組不會被搜索,返回false。負(fù)值絕對值超過長數(shù)組度,重置從0開始搜索。

返回值: 返回布爾
7、立即執(zhí)行函數(shù)

聲明一個匿名函數(shù),馬上調(diào)用這個匿名函數(shù)。目的是保護(hù)內(nèi)部變量不受污染。

(function(n1, n2) {
    console.log("這是匿名函數(shù)的自執(zhí)行的第一種寫法,結(jié)果為:" + (n1 + n2))
})(10, 100);
(function start(n1, n2) {
    console.log("這是函數(shù)聲明方式的自執(zhí)行的第一種寫法,結(jié)果為:" + (n1 + n2))
})(10, 100);
(function(n1, n2) {
    console.log("這是匿名函數(shù)的自執(zhí)行的第二種寫法,結(jié)果為:" + (n1 + n2))
}(10, 100));
(function start(n1, n2) {
    console.log("這是函數(shù)聲明方式的自執(zhí)行的第二種寫法,結(jié)果為:" + (n1 + n2))
}(10, 100));
8、js原型和原型鏈

每個對象都會在其內(nèi)部初始化一個屬性,就是prototype(原型),當(dāng)我們訪問一個對象的屬性時,如果這個對象內(nèi)部不存在這個屬性,那么他就會去prototype里找這個屬性,這個prototype又會有自己的prototype,于是就這樣一直找下去,也就是我們平時所說的原型鏈的概念。

關(guān)系:instance.constructor.prototype = instance.proto

特點:JavaScript對象是通過引用來傳遞的,我們創(chuàng)建的每個新對象實體中并沒有一份屬于自己的原型副本,當(dāng)我們修改原型時,與之相關(guān)的對象也會繼承這一改變。 當(dāng)我們需要一個屬性時,JavaScript引擎會先看當(dāng)前對象中是否有這個屬性,如果沒有的話,就會查找它的prototype對象是否有這個屬性,如此遞推下去,一致檢索到Object內(nèi)建對象。

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方法的總結(jié)。

10、Promise

一句話概括Promise:Promise對象用于異步操作,它表示一個尚未完成且預(yù)計在未來完成的異步操作。

promise是用來解決兩個問題的:

回調(diào)地獄,代碼難以維護(hù),常常第一個的函數(shù)的輸出是第二個函數(shù)的輸入這種現(xiàn)象

promise可以支持多個并發(fā)的請求,獲取并發(fā)請求中的數(shù)據(jù)

這個promise可以解決異步的問題,本身不能說promise是異步的

/*Promise 的簡單實現(xiàn)*/

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 函數(shù)

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。 進(jìn)一步說,async函數(shù)完全可以看作多個異步操作,包裝成的一個 Promise 對象,而await命令就是內(nèi)部then命令的語法糖。

待補充。。。

12、深拷貝、淺拷貝

淺拷貝和深拷貝都只針對于引用數(shù)據(jù)類型,淺拷貝只復(fù)制指向某個對象的指針,而不復(fù)制對象本身,新舊對象還是共享同一塊內(nèi)存;但深拷貝會另外創(chuàng)造一個一模一樣的對象,新對象跟原對象不共享內(nèi)存,修改新對象不會改到原對象;

區(qū)別:淺拷貝只復(fù)制對象的第一層屬性、深拷貝可以對對象的屬性進(jìn)行遞歸復(fù)制;

淺拷貝的實現(xiàn)方式

    自定義函數(shù)

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};

深拷貝的實現(xiàn)方式

    JSON.stringify 和 JSON.parse

用 JSON.stringify 把對象轉(zhuǎn)換成字符串,再用 JSON.parse 把字符串轉(zhuǎn)換成新的對象。

let newObj = JSON.parse(JSON.stringify(obj));

    lodash

用 lodash 函數(shù)庫提供的 _.cloneDeep 方法實現(xiàn)深拷貝。

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子元素是否為對象或數(shù)組,如果是,遞歸復(fù)制
                if (obj[key] && typeof obj[key] === "object") {
                    objClone[key] = this.deepClone(obj[key]);
                } else {
                    //如果不是,簡單復(fù)制
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
}
13、跨域

跨域需要針對瀏覽器的同源策略來理解,同源策略指的是請求必須是同一個端口,同一個協(xié)議,同一個域名,不同源的客戶端腳本在沒有明確授權(quán)的情況下,不能讀寫對方資源。

受瀏覽器同源策略的影響,不是同源的腳本不能操作其他源下面的對象。想要操作另一個源下的對象是就需要跨域。

jsonp

iframe

跨域資源共享(CORS)

nginx 代理跨域

14、for in 和 for of

for in

1.一般用于遍歷對象的可枚舉屬性。以及對象從構(gòu)造函數(shù)原型中繼承的屬性。對于每個不同的屬性,語句都會被執(zhí)行。
2.不建議使用for in 遍歷數(shù)組,因為輸出的順序是不固定的。
3.如果迭代的對象的變量值是null或者undefined, for in不執(zhí)行循環(huán)體,建議在使用for in循環(huán)之前,先檢查該對象的值是不是null或者undefined

for of

1.for…of 語句在可迭代對象(包括 Array,Map,Set,String,TypedArray,arguments 對象等等)上創(chuàng)建一個迭代循環(huán),調(diào)用自定義迭代鉤子,并為每個不同屬性的值執(zhí)行語句

遍歷對象

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、如何阻止冒泡?

冒泡型事件:事件按照從最特定的事件目標(biāo)到最不特定的事件目標(biāo)(document對象)的順序觸發(fā)。

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、如何阻止默認(rèn)事件?

w3c的方法是e.preventDefault(),IE則是使用e.returnValue = false

//阻止瀏覽器的默認(rèn)行為 
function stopDefault( e ) { 
    //阻止默認(rèn)瀏覽器動作(W3C) 
    if ( e && e.preventDefault ) 
        e.preventDefault(); 
    //IE中阻止函數(shù)器默認(rèn)動作的方式 
    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 

// 重復(fù)聲明
let b  = 200;//報錯

其實這里很容易理解,var是可以變量提升的。而let和const是必須聲明后才能調(diào)用的。 對于let和const來說,這里就是暫緩性死區(qū)。

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相當(dāng)于 把類的原型拿過來 
        //  People.call(this, props)
        super(props)
    }
    callMyApple() {
        console.log("我是汪某!")
    }
}

let a = new Name("啊啊啊")
a.callMyName(); //汪某
a.callMyApple(); // 我是汪某!
19、Set

Set數(shù)據(jù)結(jié)構(gòu)類似數(shù)組,但所有成員的值唯一。

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

// 數(shù)組去重
[...new Set([1,2,3,4,4,4])];// [1,2,3,4]

方法

add(value):添加某個值,返回 Set 結(jié)構(gòu)本身。

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結(jié)構(gòu)提供了“值—值”的對應(yīng),是一種更完善的 Hash 結(jié)構(gòu)實現(xiàn)。

let a = new Map();
let b = {name: "leo" };
a.set(b,"my name"); // 添加值
a.get(b);           // 獲取值
a.size;      // 獲取總數(shù)
a.has(b);    // 查詢是否存在
a.delete(b); // 刪除一個值
a.clear();   // 清空所有成員 無返回

基本使用

傳入數(shù)組作為參數(shù),指定鍵值對的數(shù)組。

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 結(jié)構(gòu)中被視為兩個鍵。

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]
三、手?jǐn)]代碼 1、實現(xiàn)一個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、實現(xiàn)一個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的模擬實現(xiàn)

3、實現(xiàn)一個Function.bind
Function.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的模擬實現(xiàn)

4、實現(xiàn)一個繼承
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"
        //定義狀態(tài)改變前的初始狀態(tài)
    self.value = undefined;
    //定義狀態(tài)為resolved的時候的狀態(tài)
    self.reason = undefined;
    //定義狀態(tài)為rejected的時候的狀態(tài)
    function resolve(value) {
        //兩個==="pending",保證了狀態(tài)的改變是不可逆的
        if (self.status === "pending") {
            self.value = value;
            self.status = "resolved";
        }
    }
    function reject(reason) {
        //兩個==="pending",保證了狀態(tài)的改變是不可逆的
        if (self.status === "pending") {
            self.reason = reason;
            self.status = "rejected";
        }
    }
    //捕獲構(gòu)造異常
    try {
        constructor(resolve, reject);
    } catch (e) {
        reject(e);
    }
}

//同時,需要在 myPromise的原型上定義鏈?zhǔn)秸{(diào)用的 then方法:
myPromise.prototype.then = function(
                 
               
              

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/7398.html

相關(guān)文章

  • 前端最強面經(jīng)匯總

    摘要:獲取的對象范圍方法獲取的是最終應(yīng)用在元素上的所有屬性對象即使沒有代碼,也會把默認(rèn)的祖宗八代都顯示出來而只能獲取元素屬性中的樣式。因此對于一個光禿禿的元素,方法返回對象中屬性值如果有就是據(jù)我測試不同環(huán)境結(jié)果可能有差異而就是。 花了很長時間整理的前端面試資源,喜歡請大家不要吝嗇star~ 別只收藏,點個贊,點個star再走哈~ 持續(xù)更新中……,可以關(guān)注下github 項目地址 https:...

    wangjuntytl 評論0 收藏0
  • 優(yōu)秀文章收藏(慢慢消化)持續(xù)更新~

    摘要:整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學(xué)習(xí)原文協(xié)作規(guī)范中文技術(shù)文檔協(xié)作規(guī)范阮一峰編程風(fēng)格凹凸實驗室前端代碼規(guī)范風(fēng)格指南這一次,徹底弄懂執(zhí)行機制一次弄懂徹底解決此類面試問題瀏覽器與的事件循環(huán)有何區(qū)別筆試題事件循環(huán)機制異步編程理解的異步 better-learning 整理收藏一些優(yōu)秀的文章及大佬博客留著慢慢學(xué)習(xí) 原文:https://www.ahwgs.cn/youxiuwenzhan...

    JeOam 評論0 收藏0
  • 前端必須要珍藏的技術(shù)文章和面試

    摘要:前端工程師學(xué)習(xí)資料,快速查找面試題,經(jīng)典技術(shù)文章的總結(jié),編程技巧,幫助學(xué)習(xí)者快速定位問題花點時間整理出一下前端工程師日常工作所需要的學(xué)習(xí)資料查找,幫助學(xué)習(xí)者快速掌握前端工程師開發(fā)的基本知識編程始于足下記住再牛逼的夢想也抵不住傻逼似的堅持蝴蝶 前端工程師學(xué)習(xí)資料,快速查找面試題,經(jīng)典技術(shù)文章的總結(jié),編程技巧,幫助學(xué)習(xí)者快速定位問題花點時間整理出一下web前端工程師日常工作所需要的學(xué)習(xí)資料...

    MoAir 評論0 收藏0
  • 平時積累的前端資源,持續(xù)更新中。。。

    本文收集學(xué)習(xí)過程中使用到的資源。 持續(xù)更新中…… 項目地址 https://github.com/abc-club/f... 目錄 vue react react-native Weex typescript Taro nodejs 常用庫 css js es6 移動端 微信公眾號 小程序 webpack GraphQL 性能與監(jiān)控 高質(zhì)文章 趨勢 動效 數(shù)據(jù)結(jié)構(gòu)與算法 js core 代碼規(guī)范...

    acrazing 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<