2019口试笔记

一.js原始范例:

在js中,存在着6种原始值:

* boolean 
* number 
* string 
* undefined 
* null 
* symbol 

注重: 虽然typeof null输出的是object,然则null并非object范例,由于初期的bug;

number范例是浮点数范例,所以才会有js精度题目涌现。0.1+0.2 !== 0.3。 原始范例存储的都是值,是没有函数可以挪用的。 
  1. symbol范例: symbol范例的对象永久不相等,即使建立他们的时刻传入了雷同的值,可以借助此特征处置惩罚属性名的争执题目。
    for…in..拿不到symbol范例的属性值,而且要用[]的体式格局来读取symbol范例的属性值,用点的体式格局读不到。

二.对象(Object)范例:

在js中,除了原始范例其他的就是对象范例了。
Q1:对象范例和原始范例的差别之处?

答:对象范例和原始范例差别的是,原始范例存贮的是值,对象谁人范例存储的是地点(指针)。当建立了一个对象范例的时刻,计算机回在内存
中拓荒一个空间赖寄存值,然则我们须要找到这个空间,这个控件会具有一个地点(指针)。当我们将变量赋值给别的一个变量时,复制的是底本变量的地点(指针)。 

Q2:函数参数是对象会发作什么?

答:函数参数是对象的话,在函数内部可能会转变这个参数对象,天生新对象。

三.typeof VS instanceof

Q1:typeof是不是能准确推断范例?

答:关于原始范例来讲,typeof除了null都可以准确显现范例,typeof null显现的是object是毛病的。关于其他的,除了function会返回function,其他都邑返回object。

Q2. instanceof能准确推断对象的道理是什么?

答:instanceof内部机制是经由历程原型链来推断对象范例的。 
  eg: const Person = function () {} 
      const p1 = new Person() p1
      instanceof Person // true 
      var str = 'hello world' str instanceof String // false 

四.范例转换:

1.转Boolean: 在前提推断时,除了undefined,null,0,-0,NaN,”,false,其他一切值都转化为true,包括一切对象。
2.对象转原始范例: 对象在转换范例的时刻,会挪用内置的[[ToPrimitive]]函数,关于该函数来讲,

算法逻辑一般来讲以下:
  * 假如已经是原始范例了,就不须要换砖了
  * 挪用x.valueof(),假如转换为基础范例,就返回转换的值
  * 挪用x.toString(),假如转化为基础范例,就返回转换的值 
  * 假如都没有返回原始范例,就会报错 1)四则运算符: 加法运算符特性: 
  *运算中假如一方为字符串,那末就会把另一方恭弘=叶 恭弘转换为字符串,1 + '1' // '11' 
  *假如一方不是字符串或许数字,那末会将它转化为数字或许字符串:true+ true // 2 ; 4 + [1,2,3] // '41,2,3' 
注重: + 'a'是快速将'a'转化成number范例的写法;'a' + + 'b' // 'aNaN' 那末关于除了加法运算符其他运算符来讲,只需一方是数字,那末另一方就会被转化为数字。横竖终究都是要转化为数字来运算。
      4 * '3' // 12 4 * [] // 0 4 * [1,2] // NaN 2)比较运算符 大于小于运算都邑转化为数字举行运算。 
关于 ==: 
*undefined 即是 null 
*字符串和数字比较时,字符串转数字 
*数字和布尔范例比较时,布尔转数字
*字符串和布尔比较时,二者转数字 

五.this

this永久指向末了挪用它的谁人对象。
1.转变this指向:

* 运用es6箭头函数 
* 在函数内部运用 _this = this 
* 运用 apply,call,bind 
* new 实例化一个对象

2.箭头函数: 箭头函数的this一直指向函数定义时的this,而非实行时(意味着假如箭头函数被非箭头函数包括,this绑定的就是近来一层非箭头函数的this)。

箭头函数中没有this绑定,必需经由历程查找作用域链来决议其值。 

3.apply,call,bind区分
apply和call只是传入的参数差别。call接收的是若干个参数列表,而apply接收的是一个包括多个参数的数组。
bind和apply,call区分:

bind建立了一个新的函数,须要手动去挪用它; 

六.new的历程:

  • 建立一个空对象obj;
  • 将新建立的空对象的隐式原型指向其组织函数的显现原型;
  • 运用call转变this的指向;
  • 假如无返回值或许返回一个非对象值,则将obj返回作为新对象;假如返回值时一个新对象的华那末直接返回该对象。

七. == VS ===

Q1: ==和 === 有什么区分?

答: 关于 == 来讲,假如两边的范例不一样的华,就会举行范例转换。
    流程: 
      * 起首推断二者范例是不是雷同 
      * 推断是不是为 undefined == null //true 
      * string转number比较 * boolean转number比较
      * object转原始范例比较 然则,=== 的比较只须要推断二者范例和值是不是雷同。 

八.闭包:

Q1: 什么是闭包?

答:函数A内部有一个函数B,函数B可以接见到函数A中的变量,那末函数B就是闭包。 

Q2:典范面试题:轮回中运用闭包处置惩罚var定义函数的题目:
答:第一种:运用闭包的体式格局: for (var i = 1; i <=5 ; i++) { ;(function(j) { setTimeout(function timer() { console.log(j) }, j * 1000) })(i)}

  第二种:用let定义的体式格局: for (let i=1 ; i <=5 ; i++) { setTimeout(function timer() { console.log(i) }, i * 1000) } Q3:闭包的优瑕玷? 闭包作用(长处):可以读取到函数内部的变量,可以让这些变量的值一直保持在内存中,不会被渣滓回收掉。

闭包瑕玷:由于闭包会使得函数中变量保留在内存中,所以会增大内存运用量,运用不当很轻易形成内存走漏。糟蹋内存。
消灭闭包:退出函数之前,将不运用的局部变量删除。

九.深浅拷贝:

1.堆和栈:栈(stack)为自动分派的内存空间,它由体系自动开释;而堆(heap)则是动态分派的内存,大小不定也不会自动开释。
2.基础数据范例寄存在栈中,数据大小肯定,内存空间大小可以分派,是直接按值寄存的,所以可以直接接见。基础范例的比较是值的比较。
3.援用范例寄存在堆中,变量实际上寄存的是栈1内存的指针,援用范例的值可变。援用范例的比较是援用的比较。所以比较两个援用范例,是看其的援用是不是指向统一个对象。
Q1.浅拷贝?

答:浅拷贝只复制一层对象的属性,并不包括对象内里的为援用范例的数据。 

Q2.深拷贝?

答: 深拷贝递归复制了对象的一切层级属性。 

Q3.深拷贝,浅拷贝以及赋值的区分?

答:浅拷贝,深拷贝和原数据都不是指向统一对象,而赋值对象和原对象是指向统一对象。
第一层数据为基础范例,转变会使原数据转变,深拷贝以及浅拷贝不会。 原数据中包括子对象,转变子对象会使赋值对象以及浅拷贝对象转变,不会使深拷贝对象转变。 

Q4.怎样完成浅拷贝?

答:1.可以经由历程Object.assign来处置惩罚。(Object.assign()要领用于将一切可罗列的值从一个或多个源对象复制到目的对象。它将返回目的对象。)
    eg: 
      let a={ age: 1 } 
      let b=O bject.assign({}, a) 
      a.age=2 console.log(b.age) // 1 
    2.可以经由历程睁开运算符...来完成浅拷贝 
    eg: 
      let a={ age: 1} 
      let b={ ...a } 
      a.age=2 console.log(b.age) // 1 

Q5.怎样完成深拷贝?

答:1.该题目可以经由历程JSON.parse(JSON.stringify(object))来处置惩罚。 
    eg: let a={age: 1, jobs: { first: 'FE' } } 
        let b=J SON.parse(JSON.stringify(a)) 
        a.jobs.first='native' 
        console.log(b.jobs.first) // FE
    然则该要领也是有局限性的: 
      * 会疏忽undefined 
      * 会疏忽symbol 
      * 不能序列化函数 
      * 不能处置惩罚轮回援用的对象 

十:原型和原型链:

js是基于原型的继续。
1.运用组织函数建立对象后,新对象与组织函数没有关联了,新对象的[[prototype]]属性指向的是组织函数的原型对象。
2.组织函数、原型和实例的关联:

* 组织函数都有一个属性prototype,这个属性是一个对象(Object的实例)
* 原型对象内里有个constractor属性,该属性指向原型对象所属的组织函数。当原型对象被修悛改,constractor就不肯定指向本来的组织函数了。
* 实例对象都有一个_proto_属性,该属性也指向组织函数的原型对象,它是一个非标准属性,不可以用于编程,它用于浏览器本身运用。

3.prototype和_proto_的关联:

* prototype是组织函数的属性;
* _proto_是实例对象的属性;
* 这二者都邑指向统一个对象。
总结:*函数也是对象,对象不肯定是函数;
      * 对象的实质:无序的键值对鸠合,键值对当中的值可以是恣意数据范例的值;
      *对象就是一个容器,这个容器当中放的是属性和要领。

4.原型链:

原型链就是可以理解为有限的实例对象和原型之间构成的有限链,就是用来完成属性同享和继续的。

5.属性搜刮:

* 在接见对象的某个成员的时刻在对象中查找是不是存在;
* 假如当前对象中没有就在组织函数的原型对象中查找;
* 假如原型对象中没有就在原型对象的原型上找;
* 直到找到Object的原型对象的原型是null为止。
eg:
  var arr = []
  原型链:arr -> Array.prototype -> Object.prototype -> null

Q1:什么是原型?

答: 原型也是一个对象,而且这个对象中包括了许多函数。原型的constract属性指向组织函数,组织函数又经由历程prototype属性指回原型,到那时并非一切函数都具有这个属性。

十一:js继续:

1.原型链继续:将父类的实例作为子类的原型。

eg:Cat.prototype = new Animal()
瑕玷:子类没法给父类传参,子类要新增属性和要领的话,必需要在new Parent()如许的语句以后实行,不然会被掩盖。

2.组织继续:运用父类的组织函数来加强子类的实例,即是是在子类的组织函数内部实行Parent.call(this)。

eg:function Cat(name) {
  Animal.call(this);
  this.name = name || 'Tom';
}
var cat = new Cat();
瑕玷:没有原型,每次建立一个子类实例都要实行一遍Parent函数。

3.组合式继续:连系原型链继续和组织继续,组合式继续在运用历程中会被挪用两次:一次是建立子类的时刻,一次是在子类组织函数的内部。

eg: function Cat(name){
    Animal.call(this);
    this.name = name || 'Tom';
  }
  Cat.prototype = new Animal();

3.class继续:

class继续的中心在于运用extends表明继续自哪一个父类,而且在子类组织函数中必需挪用super,由于这段代码可以算作Parent.call(this,value).
eg:
class Parent {
  constructor(value) {
    this.val = value
  }
  getValue() {
    console.log(this.val)
  }
}
class Child extends Parent {
  constructor(value) {
    super(value)
    this.val = value
  }
}
let child = new Child(1)
child.getValue() // 1
child instanceof Parent // true

十二:var、let及const区分:

1.var和let区分:

* let有块级作用域的说法,也就是let声明的变量只能在这个块内部运用,别的处所不能运用。var声明的变量可以在全局运用,var在函数内部声明的变量只能在函数内部运用。
* let没有变量提拔,var有变量提拔
* let声明的变量存在“暂时性死区”,而var声明的变量没有
* let不允许在统一个快内反复声明一个变量。因而也不能在函数内部反复声明一个变量。
* var声明的变量会挂载到window上,而let声明的对象不会挂载到window上。
  1. const特征:

    • const声明一个只读的常量。一旦声明,常量的值就不能转变;
    • const声明的变量必需初始化,不然会报错;
    • const声明的变量也存在暂时性死区;
    • const声明的变量只在所声明的块级作用域内有效;
    • const声明的常量也与let一样不可反复声明。

Q1.什么是提拔?

答:就是变量可以在神明之前运用,而且值为undefined。

Q2. 什么是暂时性死区?

答:在let敕令声明之前,该变量都素hi不可用的。

十三.模块化:

Q1.为何要运用模块化?

答:运用模块化可以带来以下优点:
  * 处置惩罚定名争执;
  * 供应复用性;
  * 进步代码可维护性。

Q2.完成模块化的体式格局?

CommonJS  AMD  CMD

1.require/exports:

遵照CommonJS/AMD,只能在运行时肯定模块的依靠关联及输入/输出的变量,没法举行静态优化。

2.import/export:

遵照ES6范例,支撑编译时静态剖析,便于JS引入宏和范例磨练,动态绑定。

十四、JS异步编程:

1. 并发(concurrency)和并行(parallelism)区分:
    Q1:并发与并行的区分?
        答:并发是宏观观点,我离别有使命A和使命B,在一段时间内经由历程使命间的切换完成了这个使命。
            并行是微观观点,假定CPU中存在两个中心,那末我就可以同时完成使命A和使命B。同时完成多个使命的状况可以称之为并行。
2.回调函数(callback):
    Q1.什么是回调函数?
        答:ajax(url,() => {
            //处置惩罚逻辑;
        })

    Q2.回调函数有什么瑕玷?
        答:1)回调函数有一个致命的缺点就是轻易写出回调地狱(callback hell)。
            eg:
                ajax(url, () => {
                    // 处置惩罚逻辑
                    ajax(url1, () => {
                        // 处置惩罚逻辑
                        ajax(url2, () => {
                            // 处置惩罚逻辑
                        })
                    })
                })
        回调地狱根本题目:
        * 嵌套函数存在耦合性,一旦有所修改,就会牵一发而动全身;
        * 嵌套函数一多,就很难处置惩罚毛病。
        2)回调函数不能运用trycatch捕捉毛病,不能直接return。
    Q3.怎样处置惩罚“地狱回调”?
        答:* function拆解
            * promise
            * generater
            * async/await
    3. Generator:
    4. promise:
        Q1:Promise的特性?
            答:对象的状况不受外界影响,只要三种状况:pending resolved  rejected
                状况一旦转变,就不会再变,任何时刻都可以获得这个结果。
        Q2. Promise的优瑕玷?
            答:瑕玷:* promise没法作废,一旦新建就会马上实行,没法半途作废;
                    * 假如不设置回调函数,promise内部会抛出毛病,不会反应到外部;
                    * 当处于pending状况时,没法得知现在希望到哪一个阶段(刚刚开始照样行将完成)。
                长处:可以处置惩罚回调地狱题目。
        Q3. 什么是Promise链?
            答:就是在Promise组织函数内里经由历程then来一步一步运用promise,由于then要领返回的也是一个全新的promise实例。
        Q4. Promise组织函数实行和then函数实行有什么区分?
            答:then要领每次都返回一个promise实例。
    5. Async/Await:
        Q1.async的特性?
            答:一个函数假如加上async,那末该函数就会返回一个promise。async就是将函数返回值运用Promise.resolve()包裹了一下,和then中处置惩罚返回值一样,而且await只能配套在async函数内部运用。
        Q2.优瑕玷?
            答: 长处:处置惩罚then的挪用链可以更清楚的写出代码,而且可以文雅的处置惩罚回调地狱题目。
                瑕玷:由于await将一部代码改形成了同步代码,假如多个异步代码没有依靠性却运用了await会致使性能上的下降。
        Q3.await道理是什么?
            答:await内部完成了generator。
        完成async/await:
            async function doIt() {
                console.time("doIt");
                const time1 = 300;
                const time2 = await step1(time1);
                const time3 = await step2(time2);
                const result = await step3(time3);
                console.log(`result is ${result}`);
                console.timeEnd("doIt");
            }
            
            doIt();
    6.经常使用定时器函数: setTimeout() setInterval()  requestAnimationFrame()
        requestAnimationFrame自带函数撙节功用,基础可以保证在16.6毫秒内只实行一次,而且该函数的延时结果是精准的。假如有轮回定时器的需求,requestAnimationFrame是最好的挑选。
        


    原文作者:caraline
    原文地址: https://segmentfault.com/a/1190000018411886
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞