在我心中---JS經典問題

必問

(零) AMD、CMD、CommonJs、ES6的對比

對模塊定義的規範化
解決:模塊化主要解決兩個問題,命名衝突文件依賴

AMD CMD CommonJs ES6
requireJS SeaJS Nodejs
define define module.exports export/import
AMD是預加載 CMD是懶加載
優:加載快速,並行加載 並且執行 同AMD ,不執行
缺:執行順序不可控,容易埋坑 順序執行,等待時間較長

注意:Commonjs 中 module.exportexports的區別?

返回對象不同 module.export 可以返回單獨返回一個數據類型,而 export只能返回 Object

(一)閉包

參考:https://www.cnblogs.com/shuls/p/9099176.html

簡單來說閉包就是函數套函數。
一個函數在執行開始 會給其內部的變量分配一部分內存空間,被後面語句使用,當函數執行完畢,這些變量 爲被引用後,則會釋放這些內存空間,但是,若在函數內存在一個子函數 在調用主函數的變量的時候,這些變量如果被引用 則這個子函數和這些變量 會被解析器 保存起來 形成一個閉包
優勢: 變量私有化
劣勢:容易內存泄漏, 解決方法,退出函數之前,變量刪除

(二)原型鏈

參考-面試題:https://www.cnblogs.com/wjyz/p/10219106.html
基礎:https://www.jianshu.com/p/08c07a953fa0

什麼是原型鏈?

每個對象都有原型 _proto_,而 原型 還可以由原型 ,以此類推 ,就形成了原型鏈

prototype 原型指針:是函數獨有 的,是一個函數指向一個對象 

(三)手寫繼承

參考:https://www.jianshu.com/p/6925ed009f1e
參考:https://blog.csdn.net/p312011150/article/details/83579313


1. 組合繼承

//一般情況 都是使用 call this 變量來進行變量參數傳遞 
 	function animal(name) {
      this.name = name || "動物";
      this.run = () => {
        console.log(this.name + "==>跑啊");
      };
    }
    // 原型方法
    animal.prototype.eat = function(food) {
      console.log(this.name + "正在喫:" + food);
    };
    function Dog() {
      animal.call(this);
      this.name = "狗狗";
    }
    Dog.prototype = new animal();

    let dog = new Dog();
    console.log(dog);
    console.log(dog.name);
    console.log(dog.run());
    console.log(dog.eat("6666"));

2. Object.create()

var Parent = {
    getName: function() {
        return this.name;
    }
}

var child = Object.create(Parent, {
    name: { value: "Benjamin"},
    url : { value: "http://www.zuojj.com"}
});
console.log(child);
console.log(child.getName());

3. ES6 Class Extend

class Parent {
  constructor(name){
    this.name = name;
    static sayHello(){
        console.log(this.name)
    }
  }
}


class Child extends Parent {
  constructor(name, age){
    super(name);
    this.age = age;
  }
  sayAge(){
    console.log(this.age)
    return this.age;
  }
}
let parent = new Parent("Parent");
let child = new Child("Child", 18);


(四)深copy 淺 Copy

參考:https://www.cnblogs.com/ljx20180807/p/9790239.html
參考:https://mp.weixin.qq.com/s/vXbFsG59L1Ba0DMcZeU2Bg

Object.assign({},srcObj);
如果對象的屬性值爲簡單類型 得到的新對象爲深拷貝;
如果屬性值爲對象或其它引用類型,那對於這個對象而言其實是淺拷貝的

  • 深copy
簡單版本

	  const deepClone = obj => {
        let clone = Array.isArray(obj) ? [] : {};
        for (let key in obj) {
          clone[key] = deepClone(obj[key]);
        }

        return clone;
      };

//對於數組而言 還可以使用
slice(0),concat


(五) Event Loop

參考:https://segmentfault.com/a/1190000016278115
參考:https://segmentfault.com/a/1190000018675871
Event Loop 是一個執行模型


注意:可以將 EventLoop 看成一個單線程結構 ,他將 IO 操作拋出給其他線程,繼續執行 他的 方法,在IO 先出現結束後 EventLoop 再把結果拋出主線程


Promise所有的then的回調函數是在一個microtask函數中執行的,但是每一個回調函數的執行,又按照情況分爲立即執行,微任務(microtask)和宏任務(macrotask)。

我太難了:這個解釋太不靠譜了,需要深入瞭解一下

  • 宏隊列: setTimeOut setInterval I/O 等
  • 微隊列:Promise Object.observe 等

調用棧Stack
瀏覽器執行代碼的過程
:1.執行 全部 JS 代碼, 遇到 微任務 ,宏任務,全部拋出到其各自的棧中,繼續執行
:2.JS Stack 爲空後,再次執行 微任務 ,執行完後 (一個一個的放入Stack 執行)
:3:在執行 爲首的 一個宏任務,放入Stack中執行
:4:Stack 爲空後繼續 2-4

(五)常見算法

  • 數組去重
let unique = (array)=>{
  return Array.from(new Set(array))
} 

unique = (array)=>{
 const res = new Map();//WeakSet  

 return array.filter(curr=>{
   let isIn = res.has(curr);
   if(!isIn) res.set(curr,0)//0 不重要
   return !isIn
})


}
  • 數組排序
//冒泡排序
const sortWay = (array)=>{
   for(let i=0,len =array.length;i<(len-1);i++ ){
      let curr = array[i],currNext = array[i+1];
      if(curr < currNext){//降序
          array[i]= currNext;
          array[i+1]= curr;
      }
       
   }

}

//數組自帶的sort
array = array.sort((a,b)=>{return a-b})

//數組打亂的算法
//隨機取出 20個 數
let a = [1,2,3,4,5....,50];

a = a.map((curr,index)=>{ 
  	return {value:curr,radom:Math.radom()}
})).sort((a,b)=>{
return a.radom -b-radom;
}).map(curr=>{
return curr.value;
}).slice(0,20);



談談你對js堆和棧的理解

基本問題

(一) typeof 和 instanceof 區別

  • typeof在判斷 null、array、object以及函數實例(new + 函數)時,得到的都是object
  • instanceof 判斷一個實例是否屬於某種類型 string arrray

(二)es6 常見問題

  • 基本數據類型

Number,String, Null, Undefined, Symbol, Boolean

(三)new 做了什麼

  • 創建一個新的對象
  • 新對象的 _proto_ 指向 構造對象的 prototype
  • 構造函數的作用域 賦值給新對象
  • 執行構造函數的代碼
  • 返回這新的對象

(四) arguments與arguments轉化成數組的方法

第一:這個問題很奇葩, 但是問了,不會 就尷尬了

function a(){
console.log(arguments)
}
a([1,2,3,4,5,6,7])

在這裏插入圖片描述

轉換爲數組


function a(){
 let newResult = [];
 for(let i =0,len = arguments.length;i<len;i++){
	newResult.push(arguments[i])
 }
 return newRresult;
}
a(1,2,3,4,5,6,7)

(五)數據結構

(六)跨域 和cros

參考:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Access_control_CORS

跨域

跨域:不同源 就跨域,同源是指 同 協議,同 域名,同端口,

Cros

Cros :跨域資源共享(Cross-origin resource sharing)是一種機制,出於安全原因,瀏覽器限制從JS內發起的跨源HTTP請求,並不一定是瀏覽器限制了發起跨站請求,也可能是跨站請求可以正常發起,但是返回結果被瀏覽器攔截了

衍生問題

  • 爲什麼要跨域 優缺點是?
  • 怎麼解決跨域的問題
  • 什麼情況需要Cros

跨域 xhr 請求,下載圖片 ,css 中的字體引用

  • 什麼是簡單請求 什麼 預檢請求

簡單請求 :不會 發送預檢請求 的請求 (GET、HEAD、POST)
預檢請求:會發出( OPTIONS 請求進行預先判斷允許跨域)(DELETE、PUT,OPTIONS)

  • http 常見的請求方式

HTTP請求方法並不是只有GET和POST,只是最常用的。據RFC2616標準(現行的HTTP/1.1)得知,通常有以下8種方法:OPTIONS、GET、HEAD、POST、PUT、DELETE、TRACE和CONNECT。
官方定義
HEAD方法跟GET方法相同,只不過服務器響應時不會返回消息體。一個HEAD請求的響應中,HTTP頭中包含的元信息應該和一個GET請求的響應消息相同。這種方法可以用來獲取請求中隱含的元信息,而不用傳輸實體本身。也經常用來測試超鏈接的有效性、可用性和最近的修改。
一個HEAD請求的響應可被緩存,也就是說,響應中的信息可能用來更新之前緩存的實體。如果當前實體跟緩存實體的閾值不同(可通過Content-Length、Content-MD5、ETag或Last-Modified的變化來表明),那麼這個緩存就被視爲過期了。
簡而言之
HEAD請求常常被忽略,但是能提供很多有用的信息,特別是在有限的速度和帶寬下。主要有以下特點:
1、只請求資源的首部;
2、檢查超鏈接的有效性;
3、檢查網頁是否被修改;
4、多用於自動搜索機器人獲取網頁的標誌信息,獲取rss種子信息,或者傳遞安全認證信息等

  • 這麼配置 允許Cros

Access-Control-Allow-Origin: http://foo.example – 限制允許的域名
Access-Control-Allow-Methods: POST, GET, OPTIONS – 限制允許的請求類型
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400 – 請求結果緩存時間

(七)web安全

參考:https://developer.mozilla.org/zh-CN/docs/Web/Security
例子寫得好:https://blog.csdn.net/freeking101/article/details/86537087

  • xss 攻擊 跨站腳本攻擊 是一種代碼注入攻擊

存儲型 XSS :惡意代碼存儲到 數據庫中 服務端執行
反射型 XSS :惡意代碼存在 URL 裏。服務端執行
DOM型XSS :惡意代碼僞造在URL裏, 在瀏覽器端執行

  • CSRF攻擊 跨站請求僞造

由字面上的意思 就能理解了吧應該


注意:CSRF攻擊是源於Web的隱式身份驗證機制 ,,大部分是走的cookie 做驗證機制
而Cookie 的本身會隨着域名下的所有請求達到服務端,這樣 就僞造了請求

解決方法

CSRF XSS
reffer驗證 輸入轉義
身份代碼放在 localstorage、html 或者其他位置(不放在cookie)自定義xhr header 輸入內容長度控制
動態簽名 避免拼接 HTML
- 對 各種插入數據進行編碼

(八)ES6 的箭頭函數 this 指向

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