<dl id="opymh"></dl>

<div id="opymh"></div>
      <div id="opymh"><tr id="opymh"></tr></div>

        <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

        <em id="opymh"></em>

        <em id="opymh"><ol id="opymh"></ol></em>

              频道栏目
              首页 > 程序开发 > web前端 > HTML/CSS > 正文
              2019面试笔记个人文章
              2019-03-08 15:19:16           
              收藏   我要投稿

              一.js原始类型:

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

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

              注意: 虽然typeof null输出的是object,但是null并不是object类型,因为早期的bug;

              number类型是浮点数类型,所以才会有js精度问题出现。0.1+0.2 !== 0.3。 原始类型存储的都是值,是没有函数可以调用的。 
              symbol类型: symbol类型的对象永远不相等,即便创建他们的时候传入了相同的值,可以借助此特性解决属性名的冲突问题。
              for...in..拿不到symbol类型的属性值,而且要用[]的方式来读取symbol类型的属性值,用点的方式读不到。

              二.对象(Object)类型:

              在js中,除了原始类型其他的就是对象类型了。
              Q1:对象类型和原始类型的不同之处?

              答:对象类型和原始类型不同的是,原始类型存贮的是值,对象那个类型存储的是地址(指针)。当创建了一个对象类型的时候,计算机回在内存
              中开辟一个空间赖存放值,但是我们需要找到这个空间,这个控件会拥有一个地址(指针)。当我们将变量赋值给另外一个变量时,复?#39057;?#26159;原本变量的地址(指针)。 

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

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

              三.typeof VS instanceof

              Q1:typeof是否能正?#25918;?#26029;类型?

              答:对于原始类型?#27492;擔瑃ypeof除了null都可以正确显示类型,typeof null显示的是object是错误的。对于其他的,除了function会返回function,其他都会返回object。

              Q2. instanceof能正?#25918;?#26029;对象的原理是什么?

              答: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]]函数,对于该函数?#27492;擔?/p>

              算法逻辑一般?#27492;等?#19979;:
                * 如果已经是原始类型了,就不需要换砖了
                * 调用x.valueof(),如果转换为基础类型,就返回转换的值
                * 调用x.toString(),如果转化为基础类型,就返回转换的值 
                * 如果都没有返回原始类型,就会报错 1)四则运算符: 加法运算符特点: 
                *运算中如果一方为?#22336;?#20018;,那么就会把另一方叶转换为?#22336;?#20018;,1 + '1' // '11' 
                *如果一方不是?#22336;?#20018;或者数字,那么会将它转化为数字或者?#22336;?#20018;:true+ true // 2 ; 4 + [1,2,3] // '41,2,3' 
              注意: + 'a'是快速将'a'转化成number类型的写法;'a' + + 'b' // 'aNaN' 那么对于除了加法运算符其他运算符?#27492;擔?#21482;要一方是数字,那么另一方就会被转化为数字。反正最终都是要转化为数字来运算。
                    4 * '3' // 12 4 * [] // 0 4 * [1,2] // NaN 2)比?#26174;?#31639;符 大于小于运算都会转化为数字进?#24615;?#31639;。 
              关于 ==: 
              *undefined 等于 null 
              *?#22336;?#20018;和数字比较时,?#22336;?#20018;转数字 
              *数字和布尔类型比较时,布尔转数字
              *?#22336;?#20018;和布尔比较时,两者转数字 

              五.this

              this永远指向最后调?#30431;?#30340;那个对象。
              1.改变this指向:

              * 使用es6箭头函数 
              * 在函数内部使用 _this = this 
              * 使用 apply,call,bind 
              * new ?#36947;?#21270;一个对象

              2.箭头函数: 箭头函数的this始终指向函数定义时的this,而非执行时(意味着如果箭头函数被非箭头函数包含,this绑定的就是最近一层非箭头函数的this)。

              箭头函数中没有this绑定,必须通过查找作用域链来决定其值。 

              3.apply,call,bind区别
              apply和call只是传入的参数不同。call接受的是若干个参数列表,而apply接受的是一个包含多个参数的数组。
              bind和apply,call区别:

              bind创建了一个新的函数,需要手动去调?#30431;?

              六.new的过程:

              创建一个空对象obj; 将新创建?#30446;?#23545;象的隐式原型指向其构造函数的显示原型; 使用call改变this的指向; 如果无返回值或者返回一个非对象值,则将obj返回作为新对象;如果返回值时一个新对象的华那么直接返回该对象。

              七. == VS ===

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

              答: 对于 == ?#27492;擔?#22914;果双方的类型不一样的华,就会进行类型转换。
                  流程: 
                    * 首先判断两者类型是否相同 
                    * 判断是否为 undefined == null //true 
                    * string转number比较 * boolean转number比较
                    * object转原始类型比较 但是,=== 的比?#29616;?#38656;要判断两者类型和值是否相同。 

              八.闭包:

              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:闭包的优缺点? 闭包作用(优点):可以读取到函数内部的变量,可以让这些变量的值始终保持在内存中,不会被垃圾回收掉。

              闭包缺点:因为闭包会使得函数中变量保存在内存中,所以会增大内存使用量,使用不当很容易造成内存泄漏。浪费内存。
              清除闭包?#21644;?#20986;函数之前,将不使用的局部变?#21487;?#38500;。

              九.深浅拷贝:

              1.堆和栈:栈(stack)为自动分配的内存空间,它由系统自动释放;而堆(heap)则是动态分配的内存,大小不定也不会自动释放。
              2.基本数据类型存放在栈中,数据大小确定,内存空间大小可以分配,是直接按值存放的,所以可以直接访问。基本类型的比较是值的比较。
              3.引用类型存放在堆中,变量实际上存放的是栈1内存的指针,引用类型的值可变。引用类型的比较是引用的比较。所以比较两个引用类型,是看其的引用是否指向同一个对象。
              Q1.浅拷贝?

              答:浅拷贝只复制一层对象的属性,并不包括对象里面的为引用类型的数据。 

              Q2.深拷贝?

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

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

              答:浅拷贝,深拷贝和原数据都不是指向同一对象,而赋值对象和原对象是指向同一对象。
              第一层数据为基本类型,改变会使原数据改变,深拷贝以及浅拷贝不会。 原数据中包含子对象,改变子对象会使赋值对象以及浅拷贝对象改变,不会使深拷贝对象改变。 

              Q4.如?#38382;?#29616;浅拷贝?

              答:1.可以通过Object.assign来解决。(Object.assign()方法用于将所有可枚举的值从一个或多个源对象复?#39057;?#30446;标对象。它将返回目标对象。)
                  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.如?#38382;?#29616;深拷贝?

              答: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是基于原型的?#22363;小?br /> 1.使用构造函数创建对象后,新对象与构造函数没有关系了,新对象的[[prototype]]属性指向的是构造函数的原?#25237;?#35937;。
              2.构造函数、原型和?#36947;?#30340;关系:

              * 构造函数都有一个属性prototype,这个属性是一个对象(Object的?#36947;?
              * 原?#25237;?#35937;里面有个constractor属性,该属性指向原?#25237;?#35937;所属的构造函数。当原?#25237;?#35937;被修改过,constractor就不一定指向原来的构造函数了。
              * ?#36947;?#23545;象都有一个_proto_属性,该属性也指向构造函数的原?#25237;?#35937;,它是一个非标准属性,不可以用于编程,它用于浏览器自己使用。

              3.prototype和_proto_的关系:

              * prototype是构造函数的属性;
              * _proto_是?#36947;?#23545;象的属性;
              * 这两者都会指向同一个对象。
              总结:*函数也是对象,对象不一定是函数;
                    * 对象的本质:无序的键值对集合,键值对当中的值可以是?#25105;?#25968;据类型的值;
                    *对象就是一个容器,这个容器当中放的是属?#38498;?#26041;法。

              4.原型链:

              原型链就是可以理解为有限的?#36947;?#23545;象和原型之间组成的有限链,就是用来实现属性共享和?#22363;?#30340;。

              5.属性搜索:

              * 在访问对象的某个成员的时候在对象中查找是否存在;
              * 如果当前对象中没有就在构造函数的原?#25237;?#35937;中查找;
              * 如果原?#25237;?#35937;中没有就在原?#25237;?#35937;的原型上找;
              * 直到找到Object的原?#25237;?#35937;的原型是null为止。
              eg:
                var arr = []
                原型链:arr -> Array.prototype -> Object.prototype -> null

              Q1:什么是原型?

              答: 原型也是一个对象,并且这个对象中包含了很多函数。原型的constract属性指向构造函数,构造函数又通过prototype属性指回原型,到那时并不是所有函数都具有这个属性。

              十一:js?#22363;校?/h2>

              1.原型链?#22363;校?#23558;父类的?#36947;?#20316;为子类的原型。

              eg:Cat.prototype = new Animal()
              缺点:子类无法给父类传参,子类要新增属?#38498;?#26041;法的话,必须要在new Parent()这样的语句之后执行,否则会被覆盖。

              2.构造?#22363;校?#20351;用父类的构造函数来增强子类的?#36947;?#31561;于是在子类的构造函数内部执行Parent.call(this)。

              eg:function Cat(name) {
                Animal.call(this);
                this.name = name || 'Tom';
              }
              var cat = new Cat();
              缺点:没有原型,?#30475;?#21019;建一个子类?#36947;?#37117;要执行一遍Parent函数。

              3.组合式?#22363;校?#32467;合原型链?#22363;?#21644;构造?#22363;校?#32452;合式?#22363;?#22312;使用过程中会被调用两次:一次是创建子类的时候,一次是在子类构造函数的内部。

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

              3.class?#22363;校?/p>

              class?#22363;?#30340;核心在于使用extends表明?#22363;?#33258;哪个父类,并且在子类构造函数中必须调用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在函数内?#21487;?#26126;的变量只能在函数内部使用。
              * let没有变量提升,var有变量提升
              * let声明的变量存在“暂时性死区”,而var声明的变量没有
              * let不允许在同一个快内重复声明一个变量。因此也不能在函数内部重复声明一个变量。
              * var声明的变量会挂载到window上,而let声明的对象不会挂载到window上。
              

              const特性:

              const声明一个只读的常量。一旦声明,常量的值就不能改变; const声明的变量必须初始化,不然会报错; const声明的变量也存在暂时性死区; const声明的变量只在所声明?#30446;?#32423;作用域内有效; const声明的常量也与let一样不可重复声明。

              Q1.什么是提升?

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

              Q2. 什么是暂时性死区?

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

              十三.模块化:

              Q1.为什么要使用模块化?

              答:使用模块化可以带来以下好处:
                * 解决命名冲突;
                * 提供复用性;
                * 提高代码可维护性。

              Q2.实现模块化的方式?

              CommonJS  AMD  CMD

              1.require/exports:

              遵循CommonJS/AMD,只能在运行时确定模块的依赖关系及输入/输出的变量,无法进行静态优化。

              2.import/export:

              遵循ES6规范,支持编译时静态分析,便于JS引入宏和类型检验,动态绑定。
              
              点击复制链接 与好友分享!回本站首页
              相关TAG标签 js
              上一篇:我理解的core目录 Angularx项目开发杂乱随笔
              下一篇:【node不完全指西】EventEmitter(事件发布/订?#21738;?#24335;)解析-考拉阅读前端团队-SegmentFault思否
              相关文章
              图文推荐
              点击?#21028;?/dd>

              关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip?#38469;?#22521;训 | 举报中心

              版权所有: 红黑联盟--致力于做实用的IT?#38469;?#23398;习网站

              极速飞艇好假
              <dl id="opymh"></dl>

              <div id="opymh"></div>
                  <div id="opymh"><tr id="opymh"></tr></div>

                    <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                    <em id="opymh"></em>

                    <em id="opymh"><ol id="opymh"></ol></em>

                          <dl id="opymh"></dl>

                          <div id="opymh"></div>
                              <div id="opymh"><tr id="opymh"></tr></div>

                                <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                                <em id="opymh"></em>

                                <em id="opymh"><ol id="opymh"></ol></em>