<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專題視頻專題問答1問答10問答100問答1000問答2000關(guān)鍵字專題1關(guān)鍵字專題50關(guān)鍵字專題500關(guān)鍵字專題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專題關(guān)鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
        問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
        當(dāng)前位置: 首頁 - 科技 - 知識百科 - 正文

        20道JS原理題助你面試一臂之力(必看)

        來源:懂視網(wǎng) 責(zé)編:小采 時間:2020-11-27 21:53:33
        文檔

        20道JS原理題助你面試一臂之力(必看)

        20道JS原理題助你面試一臂之力(必看):前言 本文針對目前常見的面試題,僅提供了相應(yīng)的核心原理及思路,部分邊界細(xì)節(jié)未處理。后續(xù)會持續(xù)更新,希望對你有所幫助。 1. 實現(xiàn)一個call函數(shù) // 思路:將要改變this指向的方法掛到目標(biāo)this上執(zhí)行并返回 Function.prototype.mycall
        推薦度:
        導(dǎo)讀20道JS原理題助你面試一臂之力(必看):前言 本文針對目前常見的面試題,僅提供了相應(yīng)的核心原理及思路,部分邊界細(xì)節(jié)未處理。后續(xù)會持續(xù)更新,希望對你有所幫助。 1. 實現(xiàn)一個call函數(shù) // 思路:將要改變this指向的方法掛到目標(biāo)this上執(zhí)行并返回 Function.prototype.mycall

        前言

        本文針對目前常見的面試題,僅提供了相應(yīng)的核心原理及思路,部分邊界細(xì)節(jié)未處理。后續(xù)會持續(xù)更新,希望對你有所幫助。

        1. 實現(xiàn)一個call函數(shù)

        // 思路:將要改變this指向的方法掛到目標(biāo)this上執(zhí)行并返回
        Function.prototype.mycall = function (context) {
         if (typeof this !== 'function') {
         throw new TypeError('not funciton')
         }
         context = context || window
         context.fn = this
         let arg = [...arguments].slice(1)
         let result = context.fn(...arg)
         delete context.fn
         return result
        } 
        

        2. 實現(xiàn)一個apply函數(shù)

        // 思路:將要改變this指向的方法掛到目標(biāo)this上執(zhí)行并返回
        Function.prototype.myapply = function (context) {
         if (typeof this !== 'function') {
         throw new TypeError('not funciton')
         }
         context = context || window
         context.fn = this
         let result
         if (arguments[1]) {
         result = context.fn(...arguments[1])
         } else {
         result = context.fn()
         }
         delete context.fn
         return result
        }
        

        3. 實現(xiàn)一個bind函數(shù)

        // 思路:類似call,但返回的是函數(shù)
        Function.prototype.mybind = function (context) {
         if (typeof this !== 'function') {
         throw new TypeError('Error')
         }
         let _this = this
         let arg = [...arguments].slice(1)
         return function F() {
         // 處理函數(shù)使用new的情況
         if (this instanceof F) {
         return new _this(...arg, ...arguments)
         } else {
         return _this.apply(context, arg.concat(...arguments))
         }
         }
        }
        

        4. instanceof的原理

        // 思路:右邊變量的原型存在于左邊變量的原型鏈上
        function instanceOf(left, right) {
         let leftValue = left.__proto__
         let rightValue = right.prototype
         while (true) {
         if (leftValue === null) {
         return false
         }
         if (leftValue === rightValue) {
         return true
         }
         leftValue = leftValue.__proto__
         }
        }
        

        5. Object.create的基本實現(xiàn)原理

        // 思路:將傳入的對象作為原型
        function create(obj) {
         function F() {}
         F.prototype = obj
         return new F()
        

        6. new本質(zhì)

        function myNew (fun) {
         return function () {
         // 創(chuàng)建一個新對象且將其隱式原型指向構(gòu)造函數(shù)原型
         let obj = {
         __proto__ : fun.prototype
         }
         // 執(zhí)行構(gòu)造函數(shù)
         fun.call(obj, ...arguments)
         // 返回該對象
         return obj
         }
        }
        
        function person(name, age) {
         this.name = name
         this.age = age
        }
        let obj = myNew(person)('chen', 18) // {name: "chen", age: 18}
        
        

        7. 實現(xiàn)一個基本的Promise

        // 未添加異步處理等其他邊界情況
        // ①自動執(zhí)行函數(shù),②三個狀態(tài),③then
        class Promise {
         constructor (fn) {
         // 三個狀態(tài)
         this.state = 'pending'
         this.value = undefined
         this.reason = undefined
         let resolve = value => {
         if (this.state === 'pending') {
         this.state = 'fulfilled'
         this.value = value
         }
         }
         let reject = value => {
         if (this.state === 'pending') {
         this.state = 'rejected'
         this.reason = value
         }
         }
         // 自動執(zhí)行函數(shù)
         try {
         fn(resolve, reject)
         } catch (e) {
         reject(e)
         }
         }
         // then
         then(onFulfilled, onRejected) {
         switch (this.state) {
         case 'fulfilled':
         onFulfilled()
         break
         case 'rejected':
         onRejected()
         break
         default:
         }
         }
        }
        

        8. 實現(xiàn)淺拷貝

        // 1. ...實現(xiàn)
        let copy1 = {...{x:1}}
        
        // 2. Object.assign實現(xiàn)
        
        let copy2 = Object.assign({}, {x:1})
        
        

        9. 實現(xiàn)一個基本的深拷貝

        // 1. JOSN.stringify()/JSON.parse()
        let obj = {a: 1, b: {x: 3}}
        JSON.parse(JSON.stringify(obj))
        
        // 2. 遞歸拷貝
        function deepClone(obj) {
         let copy = obj instanceof Array ? [] : {}
         for (let i in obj) {
         if (obj.hasOwnProperty(i)) {
         copy[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i]
         }
         }
         return copy
        }
        
        

        10. 使用setTimeout模擬setInterval

        // 可避免setInterval因執(zhí)行時間導(dǎo)致的間隔執(zhí)行時間不一致
        setTimeout (function () {
         // do something
         setTimeout (arguments.callee, 500)
        }, 500)
        

        11. js實現(xiàn)一個繼承方法

        // 借用構(gòu)造函數(shù)繼承實例屬性
        function Child () {
         Parent.call(this)
        }
        // 寄生繼承原型屬性
        (function () {
         let Super = function () {}
         Super.prototype = Parent.prototype
         Child.prototype = new Super()
        })()
        

        12. 實現(xiàn)一個基本的Event Bus

        // 組件通信,一個觸發(fā)與監(jiān)聽的過程
        class EventEmitter {
         constructor () {
         // 存儲事件
         this.events = this.events || new Map()
         }
         // 監(jiān)聽事件
         addListener (type, fn) {
         if (!this.events.get(type)) {
         this.events.set(type, fn)
         }
         }
         // 觸發(fā)事件
         emit (type) {
         let handle = this.events.get(type)
         handle.apply(this, [...arguments].slice(1))
         }
        }
        
        // 測試
        let emitter = new EventEmitter()
        // 監(jiān)聽事件
        emitter.addListener('ages', age => {
         console.log(age)
        })
        // 觸發(fā)事件
        emitter.emit('ages', 18) // 18
        
        

        13. 實現(xiàn)一個雙向數(shù)據(jù)綁定

        let obj = {}
        let input = document.getElementById('input')
        let span = document.getElementById('span')
        // 數(shù)據(jù)劫持
        Object.defineProperty(obj, 'text', {
         configurable: true,
         enumerable: true,
         get() {
         console.log('獲取數(shù)據(jù)了')
         return obj['text']
         },
         set(newVal) {
         console.log('數(shù)據(jù)更新了')
         input.value = newVal
         span.innerHTML = newVal
         }
        })
        // 輸入監(jiān)聽
        input.addEventListener('keyup', function(e) {
         obj.text = e.target.value
        })
        

        完整實現(xiàn)可前往之前寫的:這應(yīng)該是最詳細(xì)的響應(yīng)式系統(tǒng)講解了

        14. 實現(xiàn)一個簡單路由

        // hash路由
        class Route{
         constructor(){
         // 路由存儲對象
         this.routes = {}
         // 當(dāng)前hash
         this.currentHash = ''
         // 綁定this,避免監(jiān)聽時this指向改變
         this.freshRoute = this.freshRoute.bind(this)
         // 監(jiān)聽
         window.addEventListener('load', this.freshRoute, false)
         window.addEventListener('hashchange', this.freshRoute, false)
         }
         // 存儲
         storeRoute (path, cb) {
         this.routes[path] = cb || function () {}
         }
         // 更新
         freshRoute () {
         this.currentHash = location.hash.slice(1) || '/'
         this.routes[this.currentHash]()
         } 
        }
        

        15. 實現(xiàn)懶加載

        <ul>
         <li><img src="./imgs/default.png" data="./imgs/1.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/2.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/3.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/4.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/5.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/6.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/7.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/8.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/9.png" alt=""></li>
         <li><img src="./imgs/default.png" data="./imgs/10.png" alt=""></li>
        </ul>
        
        let imgs = document.querySelectorAll('img')
        // 可視區(qū)高度
        let clientHeight = window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
        function lazyLoad () {
         // 滾動卷去的高度
         let scrollTop = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
         for (let i = 0; i < imgs.length; i ++) {
         // 圖片在可視區(qū)冒出的高度
         let x = clientHeight + scrollTop - imgs[i].offsetTop
         // 圖片在可視區(qū)內(nèi)
         if (x > 0 && x < clientHeight+imgs[i].height) {
         imgs[i].src = imgs[i].getAttribute('data')
         } 
         } 
        }
        // addEventListener('scroll', lazyLoad) or setInterval(lazyLoad, 1000)
        

        16. rem基本設(shè)置

        // 原始配置
        function setRem () {
         let doc = document.documentElement
         let width = doc.getBoundingClientRect().width
         let rem = width / 75
         doc.style.fontSize = rem + 'px'
        }
        // 監(jiān)聽窗口變化
        addEventListener("resize", setRem)
        

        17. 手寫實現(xiàn)AJAX

        // 1. 簡單流程
        
        // 實例化
        let xhr = new XMLHttpRequest()
        // 初始化
        xhr.open(method, url, async)
        // 發(fā)送請求
        xhr.send(data)
        // 設(shè)置狀態(tài)變化回調(diào)處理請求結(jié)果
        xhr.onreadystatechange = () => {
         if (xhr.readyStatus === 4 && xhr.status === 200) {
         console.log(xhr.responseText)
         }
        }
        
        // 2. 基于promise實現(xiàn) 
        
        function ajax (options) {
         // 請求地址
         const url = options.url
         // 請求方法
         const method = options.method.toLocaleLowerCase() || 'get'
         // 默認(rèn)為異步true
         const async = options.async
         // 請求參數(shù)
         const data = options.data
         // 實例化
         const xhr = new XMLHttpRequest()
         // 請求超時
         if (options.timeout && options.timeout > 0) {
         xhr.timeout = options.timeout
         }
         // 返回一個Promise實例
         return new Promise ((resolve, reject) => {
         xhr.ontimeout = () => reject && reject('請求超時')
         // 監(jiān)聽狀態(tài)變化回調(diào)
         xhr.onreadystatechange = () => {
         if (xhr.readyState == 4) {
         // 200-300 之間表示請求成功,304資源未變,取緩存
         if (xhr.status >= 200 && xhr.status < 300 || xhr.status == 304) {
         resolve && resolve(xhr.responseText)
         } else {
         reject && reject()
         }
         }
         }
         // 錯誤回調(diào)
         xhr.onerror = err => reject && reject(err)
         let paramArr = []
         let encodeData
         // 處理請求參數(shù)
         if (data instanceof Object) {
         for (let key in data) {
         // 參數(shù)拼接需要通過 encodeURIComponent 進行編碼
         paramArr.push(encodeURIComponent(key) + '=' + encodeURIComponent(data[key]))
         }
         encodeData = paramArr.join('&')
         }
         // get請求拼接參數(shù)
         if (method === 'get') {
         // 檢測url中是否已存在 ? 及其位置
         const index = url.indexOf('?')
         if (index === -1) url += '?'
         else if (index !== url.length -1) url += '&'
         // 拼接url
         url += encodeData
         }
         // 初始化
         xhr.open(method, url, async)
         // 發(fā)送請求
         if (method === 'get') xhr.send(null)
         else {
         // post 方式需要設(shè)置請求頭
         xhr.setRequestHeader('Content-Type','application/x-www-form-urlencoded;charset=UTF-8')
         xhr.send(encodeData)
         }
         })
        }
        
        

        18. 實現(xiàn)拖拽

        window.onload = function () {
         // drag處于絕對定位狀態(tài)
         let drag = document.getElementById('box')
         drag.onmousedown = function(e) {
         var e = e || window.event
         // 鼠標(biāo)與拖拽元素邊界的距離 = 鼠標(biāo)與可視區(qū)邊界的距離 - 拖拽元素與邊界的距離
         let diffX = e.clientX - drag.offsetLeft
         let diffY = e.clientY - drag.offsetTop
         drag.onmousemove = function (e) {
         // 拖拽元素移動的距離 = 鼠標(biāo)與可視區(qū)邊界的距離 - 鼠標(biāo)與拖拽元素邊界的距離
         let left = e.clientX - diffX
         let top = e.clientY - diffY
         // 避免拖拽出可視區(qū)
         if (left < 0) {
         left = 0
         } else if (left > window.innerWidth - drag.offsetWidth) {
         left = window.innerWidth - drag.offsetWidth
         }
         if (top < 0) {
         top = 0
         } else if (top > window.innerHeight - drag.offsetHeight) {
         top = window.innerHeight - drag.offsetHeight
         }
         drag.style.left = left + 'px'
         drag.style.top = top + 'px'
         }
         drag.onmouseup = function (e) {
         this.onmousemove = null
         this.onmouseup = null
         }
         }
        }
        

        19. 實現(xiàn)一個節(jié)流函數(shù)

        // 思路:在規(guī)定時間內(nèi)只觸發(fā)一次
        function throttle (fn, delay) {
         // 利用閉包保存時間
         let prev = Date.now()
         return function () {
         let context = this
         let arg = arguments
         let now = Date.now()
         if (now - prev >= delay) {
         fn.apply(context, arg)
         prev = Date.now()
         }
         }
        }
        
        function fn () {
         console.log('節(jié)流')
        }
        addEventListener('scroll', throttle(fn, 1000)) 
        
        

        20. 實現(xiàn)一個防抖函數(shù)

        // 思路:在規(guī)定時間內(nèi)未觸發(fā)第二次,則執(zhí)行
        function debounce (fn, delay) {
         // 利用閉包保存定時器
         let timer = null
         return function () {
         let context = this
         let arg = arguments
         // 在規(guī)定時間內(nèi)再次觸發(fā)會先清除定時器后再重設(shè)定時器
         clearTimeout(timer)
         timer = setTimeout(function () {
         fn.apply(context, arg)
         }, delay)
         }
        }
        
        function fn () {
         console.log('防抖')
        }
        addEventListener('scroll', debounce(fn, 1000)) 
        
        

        聲明:本網(wǎng)頁內(nèi)容旨在傳播知識,若有侵權(quán)等問題請及時與本網(wǎng)聯(lián)系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        20道JS原理題助你面試一臂之力(必看)

        20道JS原理題助你面試一臂之力(必看):前言 本文針對目前常見的面試題,僅提供了相應(yīng)的核心原理及思路,部分邊界細(xì)節(jié)未處理。后續(xù)會持續(xù)更新,希望對你有所幫助。 1. 實現(xiàn)一個call函數(shù) // 思路:將要改變this指向的方法掛到目標(biāo)this上執(zhí)行并返回 Function.prototype.mycall
        推薦度:
        標(biāo)簽: 原理 幫助 面試題
        • 熱門焦點

        最新推薦

        猜你喜歡

        熱門推薦

        專題
        Top
        主站蜘蛛池模板: 久久久久久精品免费看SSS| 国产成人亚洲精品影院| 亚洲国产精品一区| www.亚洲日本| a级在线免费观看| 国产成人精品日本亚洲专区| 国产精品一区二区三区免费| 中文字幕亚洲乱码熟女一区二区| XXX2高清在线观看免费视频| 亚洲深深色噜噜狠狠爱网站| 亚洲最大的黄色网| 手机在线看永久av片免费| 国产亚洲一区二区精品| 精品久久久久亚洲| www国产亚洲精品久久久| 亚洲人成图片网站| 日韩毛片无码永久免费看| 特级毛片aaaa级毛片免费| 最近中文字幕mv免费高清视频7| 亚洲an天堂an在线观看| ssswww日本免费网站片| 毛茸茸bbw亚洲人| 污污网站免费观看| 亚洲日本在线观看视频| av永久免费网站在线观看| 久99精品视频在线观看婷亚洲片国产一区一级在线 | 免费a在线观看播放| 性xxxx黑人与亚洲| 国产在线a不卡免费视频| 精品一区二区三区免费视频| 精品亚洲国产成AV人片传媒| 成人毛片免费网站| 中文在线观看免费网站| 亚洲人成在线中文字幕| 免费观看四虎精品国产永久| 婷婷亚洲综合一区二区| 亚洲色欲一区二区三区在线观看| 97免费人妻在线视频| 亚洲精品人成电影网| 四虎永久在线免费观看| 一级毛片免费毛片一级毛片免费|