JavaScript面試筆試題

JavaScript前端面試

系列文章:

HTML及HTTP面試筆試題
CSS面試筆試題

JS一些算法題:

FE-interview-questions,滿意點個star。(待更新)

0. 序

本文沒有太多基礎(chǔ)性的js內(nèi)容,推薦一本書《JavaScript高級程序設(shè)計》,基礎(chǔ)不好的同學(xué)建議先學(xué)習(xí)該本書。重點內(nèi)容:事件,閉包,作用域練,原型,繼承。

1.情簡述一下javascript的執(zhí)行環(huán)境(執(zhí)行上下文)以及所涉及到到一些概念?(該文的整體筆記丟失,詳細內(nèi)容建議查看引用鏈接)

每當(dāng)控制器轉(zhuǎn)到可執(zhí)行環(huán)境時,就會進入一個執(zhí)行環(huán)境。

而執(zhí)行環(huán)境大致分為三類:

  • 全局環(huán)境
  • 函數(shù)環(huán)境
  • eval(個人不了解,開發(fā)也不會用到不做講解)

執(zhí)行環(huán)境是靠棧來存儲,每當(dāng)開始執(zhí)行js代碼的時候,就進入到了全局執(zhí)行環(huán)境,于是乎,就把全局執(zhí)行環(huán)境壓到了這個棧(我們暫時稱它為執(zhí)行環(huán)境棧)中。

而在全局代碼中,會定義很多函數(shù),函數(shù)中又會定義很多函數(shù),而每當(dāng)控制器執(zhí)行到函數(shù)時,則就進入到了這個函數(shù)的執(zhí)行環(huán)境中。

http://www.itdecent.cn/p/cd3fee40ef59

2.sessionStorage,localStorage,cookie區(qū)別

  • 共同點:都是瀏覽器端的數(shù)據(jù)存儲,同源;
  • 不同點:
  1. cookie在同源的http請求中攜帶,瀏覽器與服務(wù)器之前回傳。cookie有路徑的概念;cookie大小不超過4k。
  2. sessionStorage(瀏覽器關(guān)閉窗口前有效)和localStorage(一直有效)達到5M或者更大。
  3. cookie在設(shè)置的有效期前有效
  4. session不在不同的瀏覽器窗口中共享,loacl共享,cookie也共享。
  5. sessionStorage和localStorage支持事件機制

3.localStorage應(yīng)該如何進行存儲?

// 將數(shù)據(jù)存在loaclStorage中

export function saveToLocal(id, key, value) {
  let seller = window.localStorage.__seller__; 
  if (!seller) {
    seller = {};
    seller[id] = {};
  } else {
    seller = JSON.parse(seller);
    if (!seller[id]) {
      seller[id] = {};
    }
  }
  seller[id][key] = value;
  window.localStorage.__seller__ = JSON.stringify(seller);
};

export function loadFromLocal(id, key, def) {
  let seller = window.localStorage.__seller__;
  if (!seller) {
    return def;
  }
  seller = JSON.parse(seller)[id];
  if (!seller) {
    return def;
  }
  let ret = seller[key];
  return ret || def;
};

4.GET與POST的區(qū)別?

  • GET與POST都是HTTP協(xié)議中的請求發(fā)送方式,實際上他們都是TCP,所能做的事情都是一樣的。
  • 不同在于,HTTP規(guī)定,發(fā)送GET請求時,在HTTP Header的請求行上就聲明GET,反之POST就聲明POST。
  • HTTP要求,GET把數(shù)據(jù)放在url上,所以GET常用于發(fā)少量的數(shù)據(jù)用于查詢;POST把數(shù)據(jù)放在body中,數(shù)據(jù)量相對較大用來存儲。
  • GET請求只發(fā)一次,POST發(fā)兩次,header返回后再發(fā)送date。

5.同源策略指的是什么?

  • 同源指的是以下三個都相同:
    • 協(xié)議相同
    • 域名相同
    • 端口相同
  • 所謂同源策略指的是:瀏覽器對不同源的腳本或者文本的訪問方式進行的限制。比如源a的js不能操作引入的源b的元素屬性。
  • 限制主要為:
    • Cookie、LocalStorage 和 IndexDB 無法讀取。
    • DOM無法獲取
    • AJAX請求不能發(fā)送

6.如何才能跨域,跨域方式有哪些?

  • 設(shè)置document.domain

Cookie是服務(wù)器寫入瀏覽器的一小段信息,只有同源的網(wǎng)頁才能共享。但是,兩個網(wǎng)頁的一級域名相同,只是二級域名不相同,瀏覽器允許通過設(shè)置document.domain共享Cookie。

www.a.com/a.html

document.domain = 'a.com';
var ifr = document.createElement('iframe');
ifr.src = 'http://www.script.a.com/b.html';
ifr.display = none;
document.body.appendChild(ifr);
ifr.onload = function(){
    var doc = ifr.contentDocument || ifr.contentWindow.document;
    // 這里就能b.html的cookie了
    ifr.cooike = doc.cookie;
};

在 script.a.com/b.html 中

document.cookie = "test1=hello";
document.domain = 'a.com';

這樣不僅能訪問b的cookie,還可以訪問b的dom,但是無法訪問到LocalStorage 和 IndexDB,而且主要限制是a,b必須一級域名必須相同。

  • window.name

瀏覽器窗口都有window.name這個屬性,這個屬性最大的特點是,無論是否同源,只要在同一個窗口里,前一個網(wǎng)頁設(shè)置了這個屬性,后一個網(wǎng)頁就可以讀取它。

在b.com/data.html中有這樣的數(shù)據(jù)

<script>
    window.name = '我是你們想要的數(shù)據(jù)。';
</script>  

現(xiàn)在a.com/index.html想獲取這個數(shù)據(jù)應(yīng)該怎么辦?通過iframe充當(dāng)中間人

<script>
    function getDate(url){
        var iframe = document.createElement('iframe');
        iframe.style.display='none';
        var state = 0;
        
        iframe.onload = function(){
            if(state == 1){
                var dataPage = iframe.contentWindow;
                var data = dataPage.name;
                console.log(data);
                dataPage.document.write('');
                dataPage.close();
                document.body.remove(iframe);
            }else
            {
                state = 1;
                iframe.contentWindow.location = url;
            }
        };
        
        // 代理源,創(chuàng)建好且設(shè)置了document.name
        iframe.src = 'a.com/b.html';
    }
    
    getData('b.com/data.html');
</script>  

些人可能會問為什么不直接把iframe的src設(shè)置為目的源(b.com/data.html)來獲取數(shù)據(jù),而是在設(shè)置為目的源之后,還要把src設(shè)置為同域名下的其他源(a.com/b.html)才獲取數(shù)據(jù)?

如果直接設(shè)置src,那么iframe和本網(wǎng)頁(a.com/index.html)會因為同源策略限制不能訪問。而把iframe先設(shè)置為目的源,再設(shè)置為同域名下的其他源,那么同域名下的其他源就和目的源共享了一個窗口,故擁有同樣window.name,并且由于是同域名下的源,并且設(shè)置了domain,故可以訪問目標(biāo)源的window.name。

state用來干什么 ?

每次設(shè)置src,都會刷新,state是標(biāo)志位,讓獲取了數(shù)據(jù)就銷毀掉。

  • window.postMessage

上面的方法都是破解,H5提供了官方的API:window.postMessage。允許跨窗口通信,不論這兩個窗口是否同源。

// 舉例來說,父窗口http://aaa.com向子窗口http://bbb.com發(fā)消息,調(diào)用postMessage方法就可以了。
var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');

postMessage方法的第一個參數(shù)是具體的信息內(nèi)容,第二個參數(shù)是接收消息的窗口的源(origin),即"協(xié)議 + 域名 + 端口"。也可以設(shè)為*,表示不限制域名,向所有窗口發(fā)送。

// 子窗口向父窗口發(fā)送消息的寫法類似。
window.opener.postMessage('Nice to see you', 'http://aaa.com');

// 父窗口和子窗口都可以通過message事件,監(jiān)聽對方的消息。
window.addEventListener('message', function(e) {
  console.log(e.data);
},false);

// event.source:發(fā)送消息的窗口
// event.origin: 消息發(fā)向的網(wǎng)址
// event.data: 消息內(nèi)容

下面的例子是,子窗口通過event.source屬性引用父窗口,然后發(fā)送消息。

window.addEventListener('message', receiveMessage);
function receiveMessage(event) {
  event.source.postMessage('Nice to see you!', '*');
}
  • AJAX

利用jsonp

// 首先,網(wǎng)頁動態(tài)插入<script>元素,由它向跨源網(wǎng)址發(fā)出請求。

function addScriptTag(src) {
  var script = document.createElement('script');
  script.setAttribute("type","text/javascript");
  script.src = src;
  document.body.appendChild(script);
}

window.onload = function () {
  addScriptTag('http://example.com/ip?callback=foo');
}

function foo(data) {
  console.log('Your public IP address is: ' + data.ip);
};

阮一峰老師:瀏覽器同源政策及其規(guī)避方法

7. AJAX模型是什么?

  • AJAX全稱為“AsynchronousJavaScript and XML” 異步的JavaScript和Xml,是一種創(chuàng)建交互式網(wǎng)頁應(yīng)用開發(fā)的新技術(shù)。
  • 運用AJAX
// 創(chuàng)建xmlHttpRequest對象
function createXmlHttp(){
    var xmlHttp;
    if(window.XMLHttpRequest){
        xmlHttp = new XMLHttpRequest();
    }else{
        xmlHttp = new ActiveXObject('Microsoft.XMLHTTP');
    }
    return xmlHttp;
}

var xhr = createXmlHttp();

// 發(fā)送請求GET或者POST
// 第三個參數(shù)代表是否異步
xhr.open('GET',url+'?date='+ new Date().getTime(),true);

//GET發(fā)送的數(shù)據(jù)在url上 POST發(fā)送的數(shù)據(jù)在send()中
xhr.send();

// 回調(diào)函數(shù)響應(yīng)
xhr.onreadystatechange=function(){
    if(xhr.readyState == 4 && xhr.status == 200){
        document.getElementById("myDiv").innerHTML=xhr.responseText;
    }
}
    
// xhr.readyState存有 XMLHttpRequest 的狀態(tài)。從 0 到 4 發(fā)生變化。
// 0: 請求未初始化
// 1: 服務(wù)器連接已建立
// 2: 請求已接收
// 3: 請求處理中
// 4: 請求已完成,且響應(yīng)已就緒

// status:狀態(tài)碼

// 如果是同步,直接調(diào)用xhr.responseText即可

8.為什么說jsonp不是真正的ajax?

  • 為什么說jsonp是ajax?

因為他們目的一樣,都是請求一個url,然后把服務(wù)器返回的數(shù)據(jù)進行處理。故jquery把jsonp封裝為ajax的一種形式。

  • 那為什么jsonp不是真正的ajax?

ajax和jsonp其實本質(zhì)上是不同的東西,ajax的核心通過XmlHttpRequest獲取非本頁面內(nèi)容,而jsnop的核心是動態(tài)加載script來調(diào)用服務(wù)器提供的js腳本。

ajax 和jsonp 不是一碼事 細讀詳解

9.property 和 attribute有什么區(qū)別?

  • property表示DOM的基礎(chǔ)屬性。
<input id='ipt' value='123' other='1111' />

console.log(document.getElementById('ipt'));

可以發(fā)現(xiàn)有attributes,value,id,以及很多我們并沒有賦值的屬性,但是并沒有other屬性。value,id這樣的就叫做DOM的基礎(chǔ)屬性。

  • 正如打印出來的結(jié)果還有一個叫attributes的屬性,類型是NamedNodeMap。這里就可以說attributes是DOM 的property的其中一個。

點擊開這個你會發(fā)現(xiàn)有

0: id
1: value
2: other
length: 3
__proto__: NamedNodeMap

這個屬性包含了顯示定義在標(biāo)簽上的屬性。

console.log(ipt.attributes.other); // other="1111";

并且

console.log(typeof ipt.attributes.other); // object

返回的是一個對象。

  • property能夠從attribute中得到同步,attribute不會同步property上的值;
in1.value = 'new value of prop';
console.log(in1.value);             // 'new value of prop'
console.log(in1.attributes.value);  // 'value="1"'

in1.attributes.value.value = 'new value of attr';
console.log(in1.value);             // 'new value of attr'
console.log(in1.attributes.value);  // 'new value of attr'

10. 關(guān)于==的強制類型轉(zhuǎn)換

image
  1. 重點:

    1. Number與String比較,String轉(zhuǎn)Number。
    2. Number與Object比較,Object轉(zhuǎn)String。
    3. 當(dāng)比較中出現(xiàn)Boolean,無論另一個數(shù)據(jù)是什么類型,都先把Boolean轉(zhuǎn)為Number。
    4. undefined與null,undefined與undefined,
      null與null都返回true。
    5. Object 與 Object只有引用相同返回true。
  2. 數(shù)據(jù)類型轉(zhuǎn)化為Boolean的規(guī)則:

    1. String的 “” 轉(zhuǎn)換為Boolean為false其他都為true
    2. Number的0和NaN轉(zhuǎn)換為Boolean為false其他都為true
    3. Object的null轉(zhuǎn)換為Boolean為false其他都為true
    4. Undefined轉(zhuǎn)換為false 不能轉(zhuǎn)換為true
[] == ![] //true

// 1.由于!的優(yōu)先級比較高,先執(zhí)行![],[]是空數(shù)組,數(shù)組是對象,由2.3(需要了解的知識文字序號),則[]轉(zhuǎn)換為boolean結(jié)果為true,![]結(jié)果就為false,表達式變?yōu)榕袛?[]==false
// 2.根據(jù)1.3,將false轉(zhuǎn)為Number,結(jié)果為0,表達式變?yōu)榕袛?[] == 0
// 3.根據(jù)1.2,將[]變?yōu)镾tring,結(jié)果為"",表達式變?yōu)榕袛?"" == 0
// 4.根據(jù)1.1,將""變?yōu)镹umber,結(jié)果為0,表達式變?yōu)榕袛?0 == 0
返回結(jié)果 true

console.log(1 == true); // 文字1.3,Number(true) = 1  ->  1 == 1 true
console.log(2 == true); // 文字1.3,Number(true) = 2  ->  2 == 1 false
console.log(0 == false);//文字 1.3,Number(false)= 0  ->  0 == 0 true
console.log(NaN == NaN);// 圖片1.c.i/1.c.ii false
console.log({} == {});// 圖片1.f {}是對象,比較引用指向的空間,因為是兩個不同的空對象,地址也不一樣 false
console.log([] == []);// 同理
console.log(null == 0);// 文字1.2 null是對象,String(null) == "null"  -> "null" == 0 ,文字1.1 Number("null") == NaN -> NaN == 0 false
console.log(undefined == 0);// 這里將執(zhí)行String(undefined),之后執(zhí)行步驟同上

總結(jié):
undefined == null,結(jié)果是true。且它倆與所有其他值比較的結(jié)果都是false。

String == Boolean,需要兩個操作數(shù)同時轉(zhuǎn)為Number。

String/Boolean == Number,需要String/Boolean轉(zhuǎn)為Number。

Object == Primitive,需要Object轉(zhuǎn)為Primitive(具體通過valueOf和toString方法)。

11.支持正則表達式的方法:

  • RegExp 對象方法
// 1. complie() 用于編譯正則表達式或改變正則表達式
let str = 'woman1manm';
let patt = /(wo)?man/g;
let str2 = str.replace(patt,'2222'); // 222212222m
let patt2 = /2222/g;
patt.compile(patt2); // 改變了正則表達式
let str3 = str2.replace(patt,'woman'); // 返回 woman1womanmm

// 2. exec() 未匹配到返回一個null,匹配到則返回一個數(shù)組arr
// arr[0]表示匹配到的這個字符串,arr[1]...arr[n]表示依次匹配到的圓括號的值,如果有的話
// 并且arr有兩個屬性,index表示第一次匹配到的字符串下標(biāo),input表示需要匹配的字符串本身
let str = '22222womanmmmmmmmanmmmmman';
let patt = /(wo)?(man)/g;
let what = patt.exec(str); 
console.log(what);

// 返回 :
// [ 'woman',
//   'wo',
//   'man',
//   index: 5,
//   input: '22222womanmmmmmmmanmmmmman' ]

// 因為patt是全局搜索,所以exec還可以繼續(xù)搜索,并且這個時候patt還有一個屬性lastIndex表示 匹配文本的最后一個字符的下一個位置

console.log(patt.lastIndex) // 10
what = patt.exec(str);
console.log(what);

// 返回 :
// [ 'man',
//   'undefined',
//   'man',
//   index: 16,
//   input: '22222womanmmmmmmmanmmmmman' ]
//當(dāng)patt再也匹配不到時,lastIndex會被重置為0

//3. test(str) 檢索字符串是否有這個模式,有返回true否則false
  • String對象方法
// 1. search(patt),搜索字符串是否含有這個匹配,如果有就返回其實位置下標(biāo),沒有就返回-1。

// 2. match(patt), 在字符串內(nèi)檢索指定的模式,返回存放匹配結(jié)果的數(shù)組,該數(shù)組內(nèi)容依賴于regexp是否具有g(shù)。
// 如果沒有g(shù),則返回的結(jié)果與exec相同。既,str.match(patt) 和 patt.exec(str)的返回結(jié)果相同。如果有g(shù),是全局匹配,則會返回所有匹配結(jié)果。

let str = '22222womanmmmmmmmanmmmmman';
let patt = /(wo)?(man)/g;
let result = str.match(patt);
console.log(result); // [ 'woman', 'man', 'man' ]

// 3. replace(patt,str) ,返回一個新的字符串,如果有g(shù)將所有匹配值換成目標(biāo)字符串,沒有則替換第一個。
// $1、$2、...、$99代表圓括號所匹配的值
var name = "Doe, John";
console.log(name.replace(/(\w+)\s*, \s*(\w+)/, "$2 $1")); // John Doe

12.常用的正則表達式:

  • 匹配一個郵箱:
/^([a-zA-Z0-9])+([a-zA-Z0-9_-\.])*@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-])+/ 

開始必須是數(shù)組英文字母開頭,然后是可以是任意數(shù)字字母下劃線或者點,然后@,之后是郵箱名,域名。

  • 匹配ip地址:
/^(\d{1,3})\.(\d{1,3})\.(\d{1,3})\.(\d{1,3})$/
  • 匹配電話號碼
/^[1][34578][0-9]{9}$/
  • 檢查輸入字符串是否是帶小數(shù)的數(shù)字格式,可以是負數(shù)
/^-?(\d+)[\.]?(\d+)$/

13. es6中的let,const和var有什么區(qū)別?

  • let的作用域是外層塊,不是外層函數(shù),而var是外層函數(shù)。
if(true){
    let a =0;
    var b =0;
}
console.log(a) // 報錯,未定義
console.log(b) // 就是0
  • let沒有聲明提升,但是有暫時性死區(qū)。
console.log(a); // 結(jié)果是報錯,不是undefined
let a = 0; 


if(true){
    var c = 0; // 報錯,因為c已經(jīng)定義在此區(qū)域了。
    let c = 0;
}
  • 重新聲明會報錯
  • const與let一樣,不同在于const引用的地址不能改變,值也不能改變。聲明必須賦值。

14.var f = function g(){ return 23; }; typeof g()結(jié)果是什么?為什么?

  • typeof f :function,因為f本來就是一個函數(shù)。
  • typeof f():number,因為f()先執(zhí)行,返回了一個數(shù)字,23.
  • typeof g:undefined,因為typeof一個未聲明的變量,都默認返回undefined。
  • typeof g():報錯,g未定義。因為function是函數(shù)表達式的形式,并且賦值給了f,所以這個函數(shù)就算f,而g只是一個匿名,只能在函數(shù)f中使用,在全局訪問不到。

15.最完美的數(shù)組去重:

function normalize(arr) {
    // 判斷傳入的是否是數(shù)組
    if (arr && Object.prototype.toString.call(arr) !== '[object Array]') {
        return;
    }

    // 當(dāng)作為對象屬性時,會發(fā)生強制類型轉(zhuǎn)換,為了區(qū)別類型,創(chuàng)建不同對象來去重。
    // 例如: 1,'1' 都會被轉(zhuǎn)化為 obj['1'],導(dǎo)致去重出錯, 故區(qū)別類型。
    const objectSet = {};

    // Object.create(null), 以防和原型上的函數(shù)名沖突。
    // 例如: obj[toString], 本來是沒有重復(fù)的,但是obj[toString]會查找到
    // 原型上的toString方法,“temp in map”會為true,故利用Object.create(null)
    // 使原型為空
    objectSet.number = Object.create(null);
    objectSet.string = Object.create(null);
    objectSet.array = Object.create(null);
    objectSet.boolean = Object.create(null);
    objectSet.object = Object.create(null);
    objectSet.undefined = Object.create(null);

    let len = arr.length, temp, type, map;

    for (let i = len - 1; i >= 0; i--) {
        temp = arr[i];
        // 取相應(yīng)的去重對象。
        if(Object.prototype.toString.call(temp) === '[object Array]'){
            map = objectSet.array;
        }else{
            type = typeof temp;
            map = objectSet[type];
        }
        if (temp in map) {
            arr.splice(i, 1);
        } else {
            map[temp] = true;
        }
    }
    return arr;
}

const arr = [1, '1', 1, 'toString', ['toString'], 1, '', 2, '', null, 'null', 2, 2, null, 3, 3];
console.log(normalize(arr));

16. 把字符串轉(zhuǎn)化為大小寫:

toUpperCase(): 轉(zhuǎn)大寫
toLowerCase(): 轉(zhuǎn)小寫

17. 為什么js是阻塞加載的?

當(dāng)引用了js的時候,瀏覽器發(fā)送一個js請求,就會一直等待請求的返回,因為瀏覽器需要一個穩(wěn)定的dom結(jié)構(gòu),而js中很有可能直接改變了dom結(jié)構(gòu),為了防止渲染好的樹又被js代碼修改,所以就會阻塞其他的下載和呈現(xiàn)。

18. 數(shù)組長度問題:

  • 為什么結(jié)果不是3?
 var arr = [];
arr[0]  = 'a';
arr[1]  = 'b';
arr.foo = 'c';
console.log(arr.length); //2 

length返回的是array數(shù)組索引長度。

var arr = [];
arr[9] = 1;
console.log(arr.length); // 10;
console.log(arr[8]); // undefines;

19. ToPrimitive()是什么?

簡單來說,就是將對象(object)轉(zhuǎn)化為原始類型(undefined, null, boolean ,string, number)的方法,在計算一些強制類型轉(zhuǎn)換時,都需要將對象轉(zhuǎn)化為原始類型再進行計算。

ToPrimitive(obj)等價于,obj.valueOf(),如果為原始值則返回結(jié)果,否則,計算obj.toString(),如果是原始值返回,否則拋出異常。

注:此處有個例外,即Date類型的對象,它會先調(diào)用toString()方法,后調(diào)用valueOf()方法。

  • 不同對象的valueOf,toString結(jié)果不同
// Array
console.log([,2,'ss'].valueOf());  // 返回數(shù)組本身[,2,'ss'] ,仍然不是原始類型
console.log([,2,'ss'].toString()); // 返回每個元素中間以逗號隔開的字符串:,2,ss

// Object
console.log({a:11,b:'uu'}.valueOf()); // 返回對象本身{ a: 11, b: 'uu' }
console.log({a:11,b:'uu'}.toString()); // 返回字符串 [object Object]

console.log(function(){return 1}.valueOf()); // 返回[Function]代表函數(shù)本身
console.log(function(){return 1}.toString()); // 返回函數(shù)定義的字符串 :function (){return 1}

20. '+new Array(017)' 的結(jié)果?

  • 017是8進制,為15 -> + new Array(15);
  • +為強制類型轉(zhuǎn)Number -> Number(new Array(15));
  • new Array(15) -> ToPrimitive([,,,,,,,,,,,,]);
  • ToPrimitive([,,,,,,,,,,,,]) -> [,,,,,,,,,,].valueOf() 結(jié)果為 [,,,,,,,,,,]
  • [,,,,,,,,,,].toString() -> ',,,,,,,,,'
  • Number(,,,,,,,,,) 為NaN

21. 不能用變量提升的思路取思考

var foo = {n: 1};
var bar = function(foo){
    console.log(foo.n)
    var foo = {n:2};
}
bar(foo);

這里有正常的傳參和執(zhí)行。

22. innerHTML, outerHTML, innerText, outerText的區(qū)別?

<div id="div1"><span>abcd</span></div>

//寫
//div.innerHTML = "<p>大米</p>";    //div保留
//div.outerHTML = "<p>大米</p>";    //div也被取代了
//div.innerText = "米老鼠";
//console.log(div);           //div中包裹米老鼠
div.outerText = '<p>www</p>'  //將原來單元素直接變成了純文本,包括外圍<div>

23. Array方法的返回結(jié)果?

  • 返回本身:reverse(),sort(),
  • 返回一個副本:concat(),slice(),map(),filter
  • 返回其他:
    • 改變數(shù)組:
      • pop:返回arr最后一個元素
      • push:返回新的長度
      • shift:返回arr第一個元素
      • unshift:返回新的長度
      • splice:返回被刪除的項目
    • 不改變:
      • join:返回字符串
      • some/every:boolean
      • findIndex:下標(biāo)

24. 常用排序時間復(fù)雜度?

image

25. AMD 和 CMD 的區(qū)別有哪些?

  • AMD規(guī)范:github.com/amdjs/amdjs-api/wiki/AMD,是RequireJS在推廣過程中對模塊化定義的規(guī)范化產(chǎn)出。
  • CMD規(guī)范:github.com/seajs/seajs/issues/242CMD 是 SeaJS 在推廣過程中對模塊定義的規(guī)范化產(chǎn)出。
  • 區(qū)別
    1. 對于模塊的依賴,AMD是提前執(zhí)行,CMD是延遲執(zhí)行。不過 RequireJS 從 2.0 開始,也改成可以延遲執(zhí)行(根據(jù)寫法不同,處理方式不同)。CMD 推崇 as lazy as possible.
    2. CMD 推崇依賴就近,AMD 推崇依賴前置。
    3. AMD 的 API 默認是一個當(dāng)多個用,CMD 的 API 嚴(yán)格區(qū)分,推崇職責(zé)單一。比如 AMD 里,require 分全局 require 和局部 require,都叫 require。CMD 里,沒有全局 require,而是根據(jù)模塊系統(tǒng)的完備性,提供 seajs.use 來實現(xiàn)模塊系統(tǒng)的加載啟動。CMD 里,每個 API 都簡單純粹。
// CMD
define(function (require, exports, module) {
    var a = require('./a')
    a.doSomething()   // 此處略去 100 行   
    var b = require('./b') // 依賴可以就近書寫   
    b.doSomething()
    // ... 
})
// AMD 默認推薦的是
define(['./a', './b'], function (a, b) {
    // 依賴必須一開始就寫好  
    a.doSomething()    // 此處略去 100 行   
    b.doSomething()   // ...
})
  • 世界上,有兩種比較流行的 JavaScript 模塊化體系,一個是 Node 實現(xiàn)的 CommonJS,另外一個是 AMD。很多類庫都同時支持 AMD 和 CommonJS,但是不支持 CMD。或許國內(nèi)有很多 CMD 模塊,但并沒有在世界上流行起來。

26.keydown、keypress、keyup的區(qū)別

  • keypress主要用來捕獲數(shù)字(shift+數(shù)字的符號)、字母(區(qū)分大小寫)、小鍵盤等除了F1-12、SHIFT、Alt、Ctrl、Insert、Home、PgUp、Delete、End、PgDn、ScrollLock、Pause、NumLock、{菜單鍵}、{開始鍵}和方向鍵外的ANSI字符。keypress事件不能對系統(tǒng)功能鍵(例如:刪除,后退等,還有中文輸入法)進行正常的響應(yīng)。
  • keypress只能響應(yīng)單個字符
  • keydown和keyup可以響應(yīng)除prscrn的所有按鍵,可以捕捉組合鍵。
  • keydown和keyup不可以判斷字符大小寫,keypress可以。(keyCode)
  • keypress事件的which值無法區(qū)分主鍵盤上的數(shù)字鍵和附鍵盤數(shù)字鍵的,而keydown、keyup的which值對主附鍵盤的數(shù)字鍵敏感。

27. 原生實現(xiàn)點擊按鈕切換彈框的隱藏,且點擊彈框以外的地方使彈框隱藏:

<!DOCTYPE html>
<html lang="en">

<head>
    <style>
        html {
            height: 100%;
        }
        
        body {
            height: 100%;
        }
        
        .div {
            height: 300px;
            width: 300px;
            background-color: rosybrown;
            transition: opacity 0.4s ease;
        }
    </style>
</head>

<body>
    <button class="btn1">toggle</button>
    <div class="div" style="opacity: 1;">
        <button class="btn2">console1</button>
        <button class="btn3">console2</button>
    </div>
    <br />
    <div class="div"></div>
    <script>
        var toggle = document.getElementsByTagName('button')[0];
        var console1 = document.getElementsByTagName('button')[1];
        var console2 = document.getElementsByTagName('button')[2];
        var div = document.getElementsByClassName('div')[0];
        var isShow = true;

        toggle.onclick = function () {
            if (isShow) {
                div.style.opacity = '0';
                isShow = false;
            } else {
                div.style.opacity = '1';
                isShow = true;
            }
        }

        div.addEventListener('click', function (e) {
            e.stopPropagation();
        }, false);

        console1.addEventListener('click', function (e) {
            console.log(1);
            // e.stopPropagation();
        }, false);

        console2.onclick = function (e) {
            console.log(2);
            // e.stopPropagation();
        }

        document.body.addEventListener('click', function (e) {
            var target = e.target;
            // 點擊toggle事件也會冒泡到body上,本身toggle的效果就沒了,所以事件在toggle時直接退出不執(zhí)行
            if(target === toggle){
                return;
            }
            div.style.opacity = '0';
            isShow = false;
        }, false);
    </script>
</body>

</html>

思路:切換隱藏很簡單,主要是點擊周圍的地方隱藏彈框。那么就在body上綁定一個事件,點擊頁面任何一個地方都隱藏,然后再去除彈框區(qū)域就行了。如何去除,就在彈框上綁定一個click事件,此事件發(fā)生后停止冒泡,那么點擊彈框上任何內(nèi)容的時候,事件都會冒泡到彈框上,然后彈框再停止冒泡,那么事件就不會走到body上,也就不會在彈框區(qū)域觸發(fā)隱藏彈框事件。

28. js單例模式:

var Universe;

(function () {

    var instance;

    Universe = function Universe() {

        if (instance) {
            return instance;
        }

        instance = this;

        // 其它內(nèi)容
        this.start_time = 0;
        this.bang = "Big";
    };
} ());

//測試代碼
var a = new Universe();
var b = new Universe();
alert(a === b); // true
a.bang = "123";
alert(b.bang); // 123
var single = (function(){
    var unique;
    function getInstance(){
        if( unique === undefined ){
            unique = new Construct();
        }
        return unique;
    }
    function Construct(){
        // ... 生成單例的構(gòu)造函數(shù)的代碼
    }
    return {
        getInstance : getInstance
    }
})();

js實現(xiàn)單例模式

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 前端開發(fā)面試知識點大綱: HTML&CSS: 對Web標(biāo)準(zhǔn)的理解、瀏覽器內(nèi)核差異、兼容性、hack、CSS基本功:...
    秀才JaneBook閱讀 2,774評論 0 25
  • 本文旨在加深對前端知識點的理解,資料來源于網(wǎng)絡(luò),由本人(博客:http://segmentfault.com/u/...
    還是那個西瓜閱讀 1,372評論 0 1
  • 本文旨在加深對前端知識點的理解,資料來源于網(wǎng)絡(luò),由本人(博客:http://segmentfault.com/u/...
    AuthorJim閱讀 467評論 0 0
  • 1.幾種基本數(shù)據(jù)類型?復(fù)雜數(shù)據(jù)類型?值類型和引用數(shù)據(jù)類型?堆棧數(shù)據(jù)結(jié)構(gòu)? 基本數(shù)據(jù)類型:Undefined、Nul...
    極樂君閱讀 5,878評論 0 106
  • 在線閱讀 http://interview.poetries.top[http://interview.poetr...
    前端進階之旅閱讀 115,559評論 24 450

友情鏈接更多精彩內(nèi)容