js面試題

冒泡:

1.event.stopPropagation(); 

   事件處理過程中,阻止了事件冒泡,但不會阻擊默認行爲(它就執行了超鏈接的跳轉)

2.return false;

   事件處理過程中,阻止了事件冒泡,也阻止了默認行爲(比如剛纔它就沒有執行超鏈接的跳轉)

還有一種有冒泡有關的:

3.event.preventDefault(); 

   如果把它放在頭部A標籤的click事件中,點擊“點擊我”。

   會發現它依次彈出:我是最裏層---->我是中間層---->我是最外層,但最後卻沒有跳轉到百度

   它的作用是:事件處理過程中,不阻擊事件冒泡,但阻擊默認行爲(它只執行所有彈框,卻沒有執行超鏈接跳轉)

創建對象:

1.new 對象
    var person = new Object();
    person.name = "lisi";
    person.age = 21;
    person.family = ["lida","lier","wangwu"];
    person.say = function(){
        alert(this.name);
    }
2.直接創建
    var person ={
        name: "lisi",
        age: 21,
        family: ["lida","lier","wangwu"],
        say: function(){
            alert(this.name);
        }
    };
3.工廠模式
function createPerson(name,age,family) {
    var o = new Object();
    o.name = name;
    o.age = age;
    o.family = family;
    o.say = function(){
        alert(this.name);
    }
    return o;
}

var person1 =  createPerson("lisi",21,["lida","lier","wangwu"]);   //instanceof無法判斷它是誰的實例,只能判斷他是對象,構造函數都可以判斷出
var person2 =  createPerson("wangwu",18,["lida","lier","lisi"]);
console.log(person1 instanceof Object);                           //true

4.構造函數
function Person(name,age,family) {
    this.name = name;
    this.age = age;
    this.family = family;
    this.say = function(){
        alert(this.name);
    }
}
var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
var person2 = new Person("lisi",21,["lida","lier","lisi"]);
console.log(person1 instanceof Object); //true
console.log(person1 instanceof Person); //true
console.log(person2 instanceof Object); //true
console.log(person2 instanceof Person); //true
console.log(person1.constructor);      //constructor 屬性返回對創建此對象的數組、函數的引用
5.原型模式
function Person() {
}

Person.prototype.name = "lisi";
Person.prototype.age = 21;
Person.prototype.family = ["lida","lier","wangwu"];
Person.prototype.say = function(){
    alert(this.name);
};
console.log(Person.prototype);   //Object{name: 'lisi', age: 21, family: Array[3]}

var person1 = new Person();        //創建一個實例person1
console.log(person1.name);        //lisi

var person2 = new Person();        //創建實例person2
person2.name = "wangwu";
person2.family = ["lida","lier","lisi"];
console.log(person2);            //Person {name: "wangwu", family: Array[3]}
// console.log(person2.prototype.name);         //報錯
console.log(person2.age);              //21
6.混合模式
function Person(name,age,family){
    this.name = name;
    this.age = age;
    this.family = family;
}

Person.prototype = {
    constructor: Person,  //每個函數都有prototype屬性,指向該函數原型對象,原型對象都有constructor屬性,這是一個指向prototype屬性所在函數的指針
    say: function(){
        alert(this.name);
    }
}

var person1 = new Person("lisi",21,["lida","lier","wangwu"]);
console.log(person1);
var person2 = new Person("wangwu",21,["lida","lier","lisi"]);
console.log(person2);

事件穿透:

fastclick

是不是數組:

arr instanceof Array

arr.length

arr.constructor === Array

Object.prototype.toString.call(arr) === '[object Array]'

深拷貝淺拷貝:

淺拷貝:直接複製

深拷貝:JSON.parse() JSON.stringify()  

             

function deepClone(obj){
    let objClone = Array.isArray(obj)?[]:{};
    if(obj && typeof obj==="object"){
        for(key in obj){
            if(obj.hasOwnProperty(key)){
                //判斷ojb子元素是否爲對象,如果是,遞歸複製
                if(obj[key]&&typeof obj[key] ==="object"){
                    objClone[key] = deepClone(obj[key]);
                }else{
                    //如果不是,簡單複製
                    objClone[key] = obj[key];
                }
            }
        }
    }
    return objClone;
} 

 閉包:

使用閉包的注意點

(1)由於閉包會使得函數中的變量都被保存在內存中,內存消耗很大,所以不能濫用閉包,否則會造成網頁的性能問題,在IE中可能導致內存泄露。解決方法是,在退出函數之前,將不使用的局部變量全部刪除。

(2)閉包會在父函數外部,改變父函數內部變量的值。所以,如果你把父函數當作對象(object)使用,把閉包當作它的公用方法(Public Method),把內部變量當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函數內部變量的值。

 Ajax 請求過程:

    (1)創建`XMLHttpRequest`對象,也就是創建一個異步調用對象.

    (2)創建一個新的`HTTP`請求,並指定該`HTTP`請求的方法、`URL`及驗證信息.

    (3)設置響應`HTTP`請求狀態變化的函數.

    (4)發送`HTTP`請求.

    (5)獲取異步調用返回的數據.

    (6)使用JavaScript和DOM實現局部刷新.

跨域:(https://segmentfault.com/a/1190000015597029

跨域原因:同源策略 

解決辦法 1.jsonp  2.ifream 3.cors(請求頭) 4.代理   

typeof返回值:

string || number|| undefined || boolean || function|| object

js的原始數據類型有哪些?

string , boolean , number , null , undefined

箭頭函數和普通函數有什麼區別?

1.箭頭函數沒有綁定this指針,普通函數的this指向調用函數的對象(匿名函數的this都指向全局window對象);
2.箭頭函數沒有構造器

數組去重:

1.創建新數組 原數組遍歷放入如果有重複則不放入

function uniq(array){
    var temp = []; //一個新的臨時數組
    for(var i = 0; i < array.length; i++){
        if(temp.indexOf(array[i]) == -1){
            temp.push(array[i]);
        }
    }
    return temp;
}

2.對象鍵值法去重

function uniq(array){
    var temp = {}, r = [], len = array.length, val, type;
    for (var i = 0; i < len; i++) {
        val = array[i];
        type = typeof val;
        if (!temp[val]) {
            temp[val] = [type];
            r.push(val);
        } else if (temp[val].indexOf(type) < 0) {
            temp[val].push(type);
            r.push(val);
        }
    }
    return r;
}

3. 排序後相鄰去除法


function uniq(array){
    array.sort();
    var temp=[array[0]];
    for(var i = 1; i < array.length; i++){
        if( array[i] !== temp[temp.length-1]){
            temp.push(array[i]);
        }
    }
    return temp;
}

4.數組下標法

function uniq(array){
    var temp = [];
    for(var i = 0; i < array.length; i++) {
        //如果當前數組的第i項在當前數組中第一次出現的位置是i,才存入數組;否則代表是重複的
        if(array.indexOf(array[i]) == i){
            temp.push(array[i])
        }
    }
    return temp;
}

5

function uniq(array){
    var temp = [];
    var index = [];
    var l = array.length;
    for(var i = 0; i < l; i++) {
        for(var j = i + 1; j < l; j++){
            if (array[i] === array[j]){
                i++;
                j = i;
            }
        }
        temp.push(array[i]);
        index.push(i);
    }
    console.log(index);
    return temp;
}

6.new set()

var items = new Set([1, 2, 4, 4, 5]);
var array = Array.from(items);
console.log(array)  // (4) [1, 2, 4, 5]

檢測一個對象是否有prop屬性,沒有就拋出異常,有的話返回true,並刪掉該屬性:

var o = {
      age:10,
      prop:"prop"
    }
    function hasProperty(pro,obj){
      if(obj.hasOwnProperty(pro)){
        delete obj.prop;
      }else{
        throw new Error("沒有該屬性");
      }
    }
    hasProperty("prop",o)
    console.log(o)

attr()和prop()的區別?

attr是自己定義屬性 prop 是修改元素固有屬性(checked、disabled ...)

touch和click有何區別?

touch有延遲等待雙擊事件

Vue的雙向綁定原理是什麼?

defineProperty

webpack原理是什麼?

合併腳本 (require)

get 和 post區別:

(1)post更安全(不會作爲url的一部分,不會被緩存、保存在服務器日誌、以及瀏覽器瀏覽記錄中) 
(2)post發送的數據更大(get有url長度限制) 
(3)post能發送更多的數據類型(get只能發送ASCII字符) 
(4)post比get慢 
(5)post用於修改和寫入數據,get一般用於搜索排序和篩選之類的操作(淘寶,支付寶的搜索查詢都是get提交),目的是資源的獲取,讀取數據 

但是在服務器端 get請求更安全,不會修改數據

爲什麼get比post更快

1.post請求包含更多的請求頭 
因爲post需要在請求的body部分包含數據,所以會多了幾個數據描述部分的首部字段(如:content-type),這其實是微乎其微的。

2.最重要的一條,post在真正接收數據之前會先將請求頭髮送給服務器進行確認,然後才真正發送數據 
post請求的過程: 
(1)瀏覽器請求tcp連接(第一次握手) 
(2)服務器答應進行tcp連接(第二次握手) 
(3)瀏覽器確認,併發送post請求頭(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送) 
(4)服務器返回100 Continue響應 
(5)瀏覽器發送數據 
(6)服務器返回200 OK響應 
get請求的過程: 
(1)瀏覽器請求tcp連接(第一次握手) 
(2)服務器答應進行tcp連接(第二次握手) 
(3)瀏覽器確認,併發送get請求頭和數據(第三次握手,這個報文比較小,所以http會在此時進行第一次數據發送) 
(4)服務器返回200 OK響應 

也就是說,目測get的總耗是post的2/3左右,這個口說無憑,網上已經有網友進行過測試。

3.get會將數據緩存起來,而post不會 
可以做個簡短的測試,使用ajax採用get方式請求靜態數據(比如html頁面,圖片)的時候,如果兩次傳輸的數據相同,第二次以後消耗的時間將會在10ms以內(chrome測試),而post每次消耗的時間都差不多。經測試,chrome和firefox下如果檢測到get請求的是靜態資源,則會緩存,如果是數據,則不會緩存,但是IE什麼都會緩存起來,當然,應該沒有人用post去獲取靜態數據吧,反正我是沒見過。

4.post不能進行管道化傳輸 
http權威指南中是這樣說的:http的一次會話需要先建立tcp連接(大部分是tcp,但是其他安全協議也是可以的),然後才能通信,如果 每次連接都只進行一次http會話,那這個連接過程佔的比例太大了!於是出現了持久連接:在http/1.0+中是connection首部中添加keep-alive值,在http/1.1中是在connection首部中添加persistent值,當然兩者不僅僅是命名上的差別,http/1.1中,持久連接是默認的,除非顯示在connection中添加close,否則持久連接不會關閉,而http/1.0+中則恰好相反,除非顯示在connection首部中添加keep-alive,否則在接收數據包後連接就斷開了。 
出現了持久連接還不夠,在http/1.1中,還有一種稱爲管道通信的方式進行速度優化:把需要發送到服務器上的所有請求放到輸出隊列中,在第一個請求發送出去後,不等到收到服務器的應答,第二個請求緊接着就發送出去,但是這樣的方式有一個問題:不安全,如果一個管道中有10個連接,在發送出9個後,突然服務器告訴你,連接關閉了,此時客戶端即使收到了前9個請求的答覆,也會將這9個請求的內容清空,也就是說,白忙活了……此時,客戶端的這9個請求需要重新發送。這對於冪等請求還好(比如get,多發送幾次都沒關係,每次都是相同的結果),如果是post這樣的非冪等請求(比如支付的時候,多發送幾次就慘了),肯定是行不通的。 
所以,post請求不能通過管道的方式進行通信!很有可能,post請求需要重新建立連接,這個過程不跟完全沒優化的時候一樣了麼?所以,在可以使用get請求通信的時候,不要使用post請求,這樣用戶體驗會更好,當然,如果有安全性要求的話,post會更好。管道化傳輸在瀏覽器端的實現還需考證,貌似默認情況下大部分瀏覽器(除了opera)是不進行管道化傳輸的,除非手動開啓!

get 傳參長度原因是由於瀏覽器本身原因

完整的HTTP請求過程(https://blog.csdn.net/u014600626/article/details/78720763

1.域名解析(DNS解析)

2.發起TCP的3次握手

3.建立TCP連接後發起http請求

4.服務器端響應http請求,瀏覽器得到html代碼

5.瀏覽器解析html代碼,並請求html代碼中的資源

6.瀏覽器對頁面進行渲染呈現給用戶

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章