手写代码汇总

  1. 手写深拷贝

    1. /**
    2. *
    3. * @param {Object} obj 要拷贝的对象
    4. * @returns
    5. */
    6. function deepClone (obj = {}) {
    7. if (typeof obj !== 'object' || obj == null) {
    8. // 如果不是对象或者数组,直接返回值
    9. return obj
    10. }
    11. // 初始化返回结果
    12. let result
    13. if (obj instanceof Array) {
    14. result = []
    15. } else {
    16. result = {}
    17. }
    18. // 遍历obj key是键名
    19. for (let key in obj) {
    20. // 保证key不是原型的属性
    21. if (obj.hasOwnProperty(key)) {
    22. // 递归调用 遇到对象或者数组会再深入一层
    23. result[key] = deepClone(obj[key])
    24. }
    25. }
    26. // 返回结果
    27. return result
    28. }
  2. 手写bind函数

    1. // 手写bind
    2. Function.prototype.myBind = function () {
    3. // 将参数拆解为数组
    4. const args = Array.prototype.slice.call(arguments)
    5. // 获取fn1.bind({ x: 100 }, 10, 20, 30)中的 { x: 100}
    6. // 即bind要绑定的对象。
    7. // 即参数第一项,让第一项弹出,剩下的就是参数。
    8. const t = args.shift()
    9. // fn1.bind({ x: 100 }, 10, 20, 30)中的fn1
    10. const self = this
    11. // 返回一个函数
    12. return function () {
    13. return self.apply(t, args)
    14. }
    15. }
  3. 手写jQuery,并考虑插件和拓展性 ```javascript class jQuery { constructor(selector) {

    1. const result = document.querySelectorAll(selector)
    2. const length = result.length
    3. for (let i = 0; i < length; i++) {
    4. // 保存DOM节点
    5. this[i] = result[i]
    6. }
    7. this.length = length
    8. this.selector = selector

    } get (index) {

    1. return this[index]

    } each (fn) {

    1. for (let i = 0; i < this.length; i++) {
    2. const elem = this[i]
    3. fn(elem)
    4. }

    } on (type, fn) {

    1. return this.each(elem => {
    2. elem.addEventListener(type, fn, false)
    3. })

    } }

// 插件 jQuery.prototype.dialog = function (info) { alert(info) } // 复写 class myJQuery extends jQuery{ constructor(selector) { super(selector) } // 新写一些方法 dialog (infp) { alert(info) } }

  1. 4. 手写promise加载一张图片
  2. ```javascript
  3. const url = 'https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fpic1.win4000.com%2Fwallpaper%2F8%2F5453005f74be2.jpg&refer=http%3A%2F%2Fpic1.win4000.com&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666593868&t=73f0cc5600170de46f2c82f95ba7e8b4'
  4. function loadImg (src) {
  5. return new Promise((reslove, reject) => {
  6. const img = document.createElement('img')
  7. img.onload = () => {
  8. reslove(img)
  9. }
  10. img.onerror = () => {
  11. reject(new Error('图片加载失败'))
  12. }
  13. img.src = src
  14. })
  15. }
  16. loadImg(url).then(img => {
  17. console.log(img.width);
  18. return img
  19. }).then(img => {
  20. console.log(img.height);
  21. }).catch(e => console.log(e))
  1. 手写promise ```javascript class MyPromise { // 属性 state = ‘pending’ // 状态 value = undefined // 成功后的值 reason = undefined // 失败的原因 resolveCallbacks = [] // pending状态下。存储成功的回调 rejectCallbacks = [] // pending状态下。存储失败的回调

    // 构造函数 constructor(fn) {

    1. const resolveHandler = (value) => {
    2. if (this.state === 'pending') {
    3. this.state = 'fulfilled'
    4. this.value = value
    5. this.resolveCallbacks.forEach(fn => fn(this.value))
    6. }
    7. }
    8. const rejectHandler = (reason) => {
    9. if (this.state === 'pending') {
    10. this.state = 'rejected'
    11. this.reason = reason
    12. this.rejectCallbacks.forEach(fn => fn(this.reason))
    13. }
    14. }
    15. try {
    16. fn(resolveHandler, rejectHandler)
    17. } catch (err) {
    18. rejectHandler(err)
    19. }

    }

    // 方法 then (fn1, fn2) {

    1. // 当pending状态下,fn1和fn2会存储到callbacks里
    2. // 判断是不是函数
    3. fn1 = typeof fn1 === 'function' ? fn1 : (v) => v
    4. fn2 = typeof fn2 === 'function' ? fn2 : (e) => e
    5. if (this.state === 'pending') {
    6. return new MyPromise((resolve, reject) => {
    7. // 往数组里面加一个回调函数 状态变化的时候执行
    8. this.resolveCallbacks.push(() => {
    9. try {
    10. // 计算新值
    11. const newValue = fn1(this.value)
    12. resolve(newValue)
    13. } catch (err) {
    14. reject(err)
    15. }
    16. })
    17. this.rejectCallbacks.push(() => {
    18. try {
    19. // 计算新值
    20. const newReason = fn2(this.reason)
    21. reject(newReason)
    22. } catch (err) {
    23. reject(err)
    24. }
    25. })
    26. })
    27. }
    28. if (this.state === 'fulfilled') {
    29. return new MyPromise((resolve, reject) => {
    30. try {
    31. // 计算新值
    32. const newValue = fn1(this.value)
    33. resolve(newValue)
    34. } catch (err) {
    35. reject(err)
    36. }
    37. })
    38. }
    39. if (this.state === 'rejected') {
    40. return new MyPromise((resolve, reject) => {
    41. try {
    42. // 计算新值
    43. const newReason = fn2(this.reason)
    44. reject(newReason)
    45. } catch (err) {
    46. reject(err)
    47. }
    48. })
    49. }

    }

    catch (fn) {

    1. // catch是then的一个语法糖,只能传入失败的回调,then可以传入两个
    2. return this.then(null, fn)

    } }

// 全局静态函数 MyPromise.resolve = function (value) { return new MyPromise((resolve, reject) => resolve(value)) } MyPromise.reject = function (reason) { return new MyPromise((resolve, reject) => reject(reaon)) } // 传入promise数组,等到所有的都fulfilled之后,返回新的promise MyPromise.all = function (promiseList = []) { return new MyPromise((resolv, reject) => { const result = [] const length = promiseList.length let resolvedCount = 0 promiseList.forEach(p => { p.then(data => { result.push(data) resolvedCount++

  1. if (resolvedCount === length) {
  2. // 已经遍历到了最后
  3. resolv(result)
  4. }
  5. }).catch(err => {
  6. reject(err)
  7. })
  8. })
  9. })

} // 传入promise数组,只要有一个fulfilled即可返回 MyPromise.race = function (promiseList = []) { let resolved = false return new MyPromise((resolve, reject) => { promiseList.forEach(p => { p.then(data => { if (!resolved) { resolve(data) resolved = true } }).catch(err => { reject(err) }) }) }) }

  1. 6. 手写Ajax
  2. ```javascript
  3. function ajax (url) {
  4. const p = new Promise((reslove, reject) => {
  5. const xhr = new XMLHttpRequest()
  6. xhr.open('GET', url, true)
  7. xhr.onreadystatechange = function () {
  8. if (xhr.readyState === 4) {
  9. if (xhr.status === 200) {
  10. reslove(JSON.parse(xhr.responseText))
  11. } else if (xhr.status === 404) {
  12. reject(new Error('404 not found'))
  13. }
  14. }
  15. }
  16. // 只有send才可以改变状态
  17. xhr.send(null)
  18. })
  19. return p
  20. }
  21. const url = './text.json'
  22. ajax(url)
  23. .then(res => console.log(res))
  24. .catch(err => console.error(err))

面试技巧

关于简历

  1. 简洁明了,突出个人技巧和项目经验
  2. 可以把个人博客、开源作品放在简历中(但博客要有内容)
  3. 不要造假,保证能力上的真实性(斟酌用词,如精通)

    注意事项

  4. 如何看待加班:像借钱,救急不救穷

  5. 千万不要挑战面试官,反考面试官
  6. 学会给面试官惊喜,证明你能想到更多,做的更好,但不要太多
  7. 遇到不会的问题,说出你知道的部分即可,但别岔开话题
  8. 谈谈你的缺点:说一下你最近在学什么即可