美文网首页前端面试之路
「JavaScript」 基础知识要点及常考面试题(一)

「JavaScript」 基础知识要点及常考面试题(一)

作者: ybrelax | 来源:发表于2019-02-25 18:05 被阅读0次

    数据类型


    原始类型有哪几种?null 是对象嘛?

    • null
    • undefined
    • string
    • boolean
    • number
    • symbol (es6 新增)

    typeof null 输出的Object,但是对于js来说它还是作为一个基本类型
    typeof :
    原始数据类型的判断采用 typeof ,
    原理: 不同的对象在底层都表示为二进制, 在 JavaScript 中二进制前三位都为 0 的话会被判断为 object 类型, null 的二进制表示是全 0, 自然前三位也是 0, 所以执行 typeof 时会返回“object”。
    instanceof:
    引用数据类型的判断采用 instanceof
    原理:通过原型链去判断

    原始类型和对象类型的区别

    原始类型存储的是值,对象类型存储的是一个地址

    • 判断一个变量是否未定义
      首先如果单纯的使用未定义,浏览器会报错
      typeof xx == undefined
      用这个可以判断是否未定义

    对象

    for/in、Object.keys 和 Object.getOwnPropertyNames 对属性遍历有什么区别?你还知道其他遍历对象属性的方式吗?请说明。

    ES6 一共有 5 种方法可以遍历对象的属性。

    var parent = {}
    Object.defineProperties(parent, {
        a: {
            value: 1,
            writable: true,
            enumerable: true,
            configurable: true
        },
        b: {
            value: 1,
            writable: true,
            enumerable: false,
            configurable: true
        },
        [Symbol('parent')]: {
            value: 1,
            writable: true,
            enumerable: true,
            configurable: true
        }
    })
    var child = Object.create(parent, {
        c: {
            value: 1,
            writable: true,
            enumerable: true,
            configurable: true
        },
        d: {
            value: 1,
            writable: false,
            enumerable: true,
            configurable: true
        },
        e: {
            value: 1,
            writable: true,
            enumerable: false,
            configurable: true
        },
        f: {
            value: 1,
            writable: true,
            enumerable: true,
            configurable: false
        },
        [Symbol('child')]: {
            value: 1,
            writable: true,
            enumerable: true,
            configurable: true
        }
    })
    
    1. for...in
      for...in循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。
    for (const key in child) {
        console.log(key)
    }
    // c d f a
    
    1. Object.keys(obj)
      Object.keys返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名。
    Object.keys(child)
    // ["c", "d", "f"]
    
    1. Object.getOwnPropertyNames(obj)
      Object.getOwnPropertyNames返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。
    Object.getOwnPropertyNames(child)
    // ["c", "d", "e", "f"]
    
    1. Object.getOwnPropertySymbols(obj)
    Object.getOwnPropertySymbols(child)
    // [Symbol(child)]
    

    Object.getOwnPropertySymbols返回一个数组,包含对象自身的所有 Symbol 属性的键名。

    1. Reflect.ownKeys(obj)
      Reflect.ownKeys返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
    Reflect.ownKeys(child)
    // ["c", "d", "e", "f", Symbol(child)]
    

    类数组转换为数组有哪几种实现方式?

    类数组对象:只包含使用从零开始,且自然递增的整数做键名,并且定义了length表示元素个数的对象,我们就认为他是类数组对象!

    var obj = {
        0: 'a',
        1: 'b',
        length: 2
    }
    console.log(Array.from(obj))
    console.log(Array.prototype.slice.call(obj))
    console.log([].slice.call(obj))
    

    字符串

    常见的字符串方法

    • str.charAt(index); 返回子字符串,index为字符串下标
    • str.charCodeAt(index); 返回字符串的unicode编码
    • str.indexOf(searchString,startIndex); 返回子字符串第一次出现的位置,从startIndex开始查找
    • str.lastIndexOf(searchString,startIndex); 从由往左找子字符串,找不到时返回-1
    • str.substring(start,end); 两个参数都为正数,返回值:[start,end) 也就是说返回从start到end-1的字符(有一点比较重要的是,start和end的参数是可以互换的,小的在前面,大的在后面)
    • str.slice(start,end); 两个参数可正可负,负值代表从右截取,(-1 指字符串的最后一个字符,-2 指倒数第二个字符,以此类推。) 返回值:(start,end) 也就是说返回从start到end-1的字符
    • str.substr(start,length); start参数可正可负,负数代表从右截取
      区别
    • str.split(separator,limit); 参数1指定字符串或正则,参照2指定数组的最大长度
    • str.replace(rgExp/substr,replaceText) 返回替换后的字符串
    • str.match(rgExp); 正则匹配, 匹配到则返回匹配的文字
      字符串比较
      字符串之间的比较:比较第一个字符的unicode编码值,第一个字符要是相同,就比较第二个

    数组

    常用的数组方法

    数组常用方法.png
    • map() 方法按照原始数组元素顺序依次处理元素。
      注意:map() 不会对空数组进行检测。
      注意: map() 不会改变原始数组。
      删除数组的方法
    • splice
    • arr[1] delete[i] delete方法删除掉数组中的元素后,会把该下标出的值置为undefined,数组的长度不会变

    会改变原来数组的有:
    pop()---删除数组的最后一个元素并返回删除的元素。

    push()---向数组的末尾添加一个或更多元素,并返回新的长度。

    shift()---删除并返回数组的第一个元素。

    unshift()---向数组的开头添加一个或更多元素,并返回新的长度。

    reverse()---反转数组的元素顺序。

    sort()---对数组的元素进行排序。

    splice()---用于插入、删除或替换数组的元素。

    map 与 forEach的区别

    • forEch 会改变原来的数组,而map不会
    let arr = [1, 2, 3, 4, 5];
    
    arr.forEach((num, index) => {
        return arr[index] = num * 2;
    });
    // arr = [2, 4,6,8,10]
    arr.map((num,index)=> {
      return num * 2;
    })
    // arr = [1, 2, 3, 4, 5];
    

    this


    如何正确的理解this

    • 案例1 先来看一段函数调用
    function foo() {
      console.log(this.a)
    }
    var a = 1
    foo()
    
    const obj = {
      a: 2,
      foo: foo
    }
    obj.foo()
    
    const c = new foo()
    

    分析:

    1. 在没有任何调用的情况, foo()的this是指向window
    2. obj.foo(), 谁调用this的指向就会指向谁
    3. new出来的对象,就绑定在c上
    • 案例2 bind
    let a = {}
    let fn = function () { console.log(this) }
    fn.bind().bind(a)()
    

    分析:
    你们以为输出的结果是a?其实不然,bind函数所绑定都是由第一次绑定的值来决定,也就是fn.bind() => window

    • this有限级说明
      首先,new 的方式优先级最高,接下来是 bind 这些函数,然后是 obj.foo() 这种调用方式,最后是 foo 这种调用方式,同时,箭头函数的 this 一旦被绑定,就不会再被任何方式所改变。

    闭包


    关于闭包的理解

    闭包是指,函数中调用函数,函数A中有函数B的存在,函数B中调用函数A的变量。

    function A() {
      let a = 1
      window.B = function () {
          console.log(a)
      }
    }
    A()
    B() // 1
    

    用途. 使用闭包去处理var关键字的问题

    for (var i = 1; i <= 5; i++) {
      ;(function(j) {
        setTimeout(function timer() {
          console.log(j)
        }, j * 1000)
      })(i)
    }
    

    缺点:

    1. 由于闭包中的变量都是存储在内存中,所有很容易导致内存泄漏
    2. 闭包中会改变父级作用域的变量值,如果把父函数当作一个对象,闭包函数当作公有方法,那么里面的成员变量就要慎用,因为闭包函数会改变其父类的变量,从而影响其他的调用

    深拷贝和浅拷贝

    对于深拷贝和浅拷贝的理解

    1. 浅拷贝
      可以使用扩展运算符(...)
    let a = {
      age: 1
    }
    let b = { ...a }
    a.age = 2
    console.log(b.age) // 1
    
    • 可以使用Object.assign(a, {1,23})
    1. 深拷贝
    • 递归考虑
    • for 循环

    原型链


    原型链的一些要点

    • 如何访问
      1. 标准原型访问器Object.getPrototypeOf(object)
      2. 非标准访问器object.proto
      3. 通用访问器,object.constructor.prototype
    • 原型上的constructor指向函数本身
    • Object.prototype确实一个特例——它的proto指向的是null
    • 原型定义的一些公用的属性和方法;利用原型创建出来的新对象实例会共享原型(的所有属性和方法)。

    下面这张图展现了原型链的整个模型

    原型链
    推荐文章 原型链精选

    相关文章

      网友评论

        本文标题:「JavaScript」 基础知识要点及常考面试题(一)

        本文链接:https://www.haomeiwen.com/subject/sqbwyqtx.html