js基础面试

141 阅读3分钟

1.变量类型

  • typeof 能判断哪些变量类型
    • 所有值类型(number,boolean,string,undefined,symbol,BigInt)
    • 识别Function
    • 判断是否是引用类型(不可细分)
  • 何时使用 === ?何时使用 == ?
    • 除 == null 外其他都是用 ===
    • == 是会进行隐式转换数据类型
  • 值类型和引用类型的区别
    • 传递方式不同:值类型是赋值传递,引用类型是引用地址传递
    • 存储方式不同:值类型是存储在栈中,引用类型是存储在堆中,把引用地址存放在栈中 (注意:考虑性能问题-值类型内存占用小,引用类型内存占用大,CPU耗时)
  • 手写深拷贝
    • 注意值类型和引用类型的区别
    • 注意对象和数组的区别
    • 递归
      function deepClone (obj) {
        if (obj typeof !== 'object' || obj == null) {
        // 判断是否是数组或对象,不是则返回
          return obj
        }
        // 初始化返回值
        let result;
        // 是数组还是对象
        if (obj instanceof Array) {
          result = []
        } else {
          reuslt = {}
        }
        // 遍历
        for (let key in obj) {
          // 判断是否是原型的属性
          if(obj.hasOwnPrototype(key)) {
            result[key] = deepClone(obj[key]) // 递归
          }
        }
        return result;
      }
      
    
变量计算-类型转换
  • 字符串拼接
      1 + '100' = 1100
    
  • ==
    100 == '100'
    0 == ''
    0 == false
    '' == false
    undefined == null
    // 以上计算都为 true
    const obj = {}
    if (obj.x == null) {}
    // 相当于
    if (obj.x == null || obj.x == undefined) {}
    
  • if语句和逻辑运算
      // truly变量: !!a === true
      // falsely变量: !!a === false
      // 以下都是falsely变量,除此之外都是truly变量
      !!0 === false
      !!null === false
      !!undefined === false
      !!'' === false
      !!NaN === false
      !!false === false
    

2.原型和原型链

  • 如何准确判断一个变量是不是数组 lat a = []; a instanceof Array
  • 手写一个简易的jQuery,考虑插件和扩展性
  class jQuery {
    // constructor 
    constructor(selector) {
      const result = document.querySelectorAll(selector); // 选择器
      const length = result.length;
      for(let i = 0; i < length; i++) {
        this[i] = result[i];// 遍历元素
      }
      this.length = length;
      this.selector = selector;
    }
    // 获取元素方法
    get(index) {
      return this[index];
    }
    // 遍历元素方法
    each(fn) {
      for(let i = 0; i < this.length; i++) {
        const elem = this[i];
        fn(elem);
      }
    }
    on(type, fn) {
      return each((elem) => {
        elem.addEventLister(type, fn, false)
      })
    }
  }
  
  // 插件
  jQuery.prototype.diago = function () {
    alert('插件')
  }
  
  // 扩展‘造轮子’
  class myjQuery extends jQuery {
    constructor (selector) {
      super(selector)
    }
    addClassName (className) {
      return this.each(elm => {
        elm.className = className
      })
    }
  }
  • 原型和原型链

    • 原型

      • 每个class都有显示原型prototype
      • 每个实例都有隐式原型 __proto__
      • 实例的__proto__指向对应class的prototype
    • 原型的执行规则

      • 获取属性或执行方法时,先在自身属性和方法上寻找,如果找不到则自动去__proto__中查找
    • 原型链

      • 原型链就是基于原型的执行规则层层往上查找,直到找到null,从而形成原型链。

image.png

3.作用域和闭包

  • this的不同应用场景,如何取值? this的指向不是定义的时候决定的,而是直执行的时候确定的
      // 当做普通函数被调用
      function foo () {
        console.log(this)
      }
      foo() // window
      foo.call({x: 1}) // {x: 1}
      var f1 = foo.bind({x: 2})
      f1() // {x: 2}
      // 箭头函数: 当前函数调用
      const student = {
        name: 'zhangsan'
        sayHi () {
          // this 即当前对象
          console.log(this)
        },
        wait () {
          setTimeout(function() {
            console.log(this) // this === window
          }
        },
        waitAgain () {
          setTimeout(() => {
            console.log(this) // this 即当前对象
          })
        }
      }
      // apply \ call \ bind
      // 作为对象函数被调用
      // 在class的方法中被调用
      
     class Student {
         constructor(name) {
             this.name = name
             this.age = 20
         }
         sayHi () {
             console.log(this)
         }
     }
     const zhangsan = new Student('zhangsan')
     console.log(zhangsan) // Student {name: 'zhangsan', age: 20}
    
  • 手写bind函数
  Function.prototype.bind1 = function () {
    // 拆解参数成数组
    const arr = Array.prototype.slice.call(arguments)
    // 截取第一个参数,即this指向
    const t = arr.shift()
    // 函数foo.bind()中的foo
    const self = this
    // 返回函数
    return function () {
      return self.apply(t, arr)
    }
  }
  function foo (a, b, c) {
    console.log(this, 'this is foo')
    console.log(a, b, c)
  }
  var f1 = foo.bind1({x: 1}, 1, 2, 3)
  var res = f1()
  console.log(res)