web架构师 web前端面试100问之JavaScript(ES6/ES7)

一、什么是原型、原型链,有什么做用?

答: 原型:每个对象都与另外一个对象相关联,那个关联的对象就称为原型。
例如:函数Person有一个属性prototype,指向一个对象,对于普通函数来讲没多意义,对于构造函数就有做用了,当使用new操做符时,会把Person.prototype(原型对象)赋值给实例的__proto__(原型实例)属性。javascript

JS有一个原型查找机制,把原来定义在实例上的方法,放到原型对象上去,经过构造函数的new操做,会把原型对象赋值给实例的__proto__属性,那么当使用返回的实例去调用某一个方法的时候,若是实例自己上没有,就去自动去实例的__proto__上去查找,这样达到方法的复用,减小内存开销。前端

原型链:每个对象,都有一个原型对象与之关联,这个原型对象它也是一个普通对象,这个普通对象也有本身的原型对象,这样层层递进,就造成了一个链条,这个链条就是原型链。经过原型链能够实现JS的继承,把父类的原型对象赋值给子类的原型,这样子类实例就能够访问父类原型上的方法了。java

2Person.prototype.constructor == Person
3
4Person.prototype.__proto__.constructor  == Object 
5
6Person.prototype.__proto__ == Object.prototype
7         
8Object.prototype.__proto__ == null

二、如何实现继承(ES5/ES6)?

10 function Anima(name){ //父类
11                  this.name = name;
12              }
13
14              Anima.prototype.sayName = function(){
15                    console.log(this.name)
16              }
17
18              function Person(name,age){ //子类
19                  Anima.call(this,name);
20                  this.age = age;
21              }
22
23              Person.prototype = Object.create(Anima.prototype, {
24                constructor: {
25                  value: Person,
26                  enumerable: false
27                }
28              })
29
30
31            var p = new Persion("haha",12);
32
            Extends //ES6

点击获取 web前端全栈架构视频课程ios

3.什么是做用域以及做用域链?

答:做用域是指程序源代码中定义变量的区域,限定一个变量可访问的范围的,做用域的本质是对象。在JS采用的词法做用域,在书写代码的时候(定义函数的时候),做用域就已经肯定好了。 在ES6环境下,包含3个做用域,全局globel,函数做用域,快级做用域( {} ) (eval)web

做用域链:由多级做用域对象,逐级引用的链式结构。本质为执行上下文的scope属性,存储全部的变量,包括局部与全局,控制变量的使用顺序。面试

var b = 10; //1:输出?2:改造代码输出10或20
(function b(){
    b = 20;
    console.log(b); 
})();

var b = 10;
(function b(b) { 在这个函数b是一个常量,在函数b内部是可使用的,可是不能修改,若是加上use strict 严格模式就会报错。
 window.b = 20;
 console.log(b) //输出10
})(b)
var a = 10;
(function () {
    console.log(a)
    a = 5
    console.log(window.a)
    var a = 20;
    console.log(a)
})()

4.什么是闭包,闭包的好处和坏处分别是?

答:当函数能够记住并访问外部做用域时,就产生了闭包,那个外部做用域就称为闭包。axios

造成的缘由:外层函数的做用域对象没法释放。
做用:保护一个变量,重用一个变量。坏处:使用不当,会形成内存泄漏。api

大白话来解释:函数A和函数B,当内部函数B引用了A 的局部变量时,函数A 称为闭包
缘由是:JS是词法做用域,B的做用域链上有对A执行环境的引用(这个执行环境用函数来表示),A的执行环境AO就不会回收。跨域

五、什么是this,this的经常使用方式有哪些?如何改变this的指向?

答:JS在运行过程当中会产生执行上下文环境(context),context记录了包含函数在哪里被调用,做用域scope,this等信息。this就是context的其中一个属性,会在函数的执行过程当中使用。This是在运行时候绑定的,它指代的上下文对象取决于函数调用的各类条件。
this提供了一种优雅的方式来隐式的传递一个对象的引用,因此在函数中使用this能够更加方便的复用函数。数组

一、全局使用 this === window 不多使用
二、函数当中 在全局调用这个fn() this === window
三、在方法当中使用 this === 调用当前这个函数的所在的对象啊
四、构造函数this执向的是 new 建立出来的实例对象啊
五、DOM事件处理函数中的this,指向当前的DOM节点
六、经过 bind,call,apply 操做符来显示的设置 this的指向

bind:绑定函数里面的this,返回新函数,
     call,apply:绑定并执行这个函数,前者传参是“,”隔开,后者是数组

七、ES6的箭头函数 箭头函数没有本身的this,父做用域的this

var x = 3;
  var foo = {
     x: 2,
     baz: {
      x: 1,
      bar: function() {
         return this.x;
        }
      }
   }

  var go = foo.baz.bar;
  go()?
foo.baz.bar()?


//综合面试题
function Foo() {
    Foo.a = function() {
        console.log(1)
    }
    this.a = function() {
        console.log(2)
    }
}
Foo.prototype.a = function() {
    console.log(3)
}
Foo.a = function() {
    console.log(4)
}
Foo.a();
let obj = new Foo();
obj.a();
Foo.a();

6.手写bind,call,apply函数

答案:以上都是Function原型上的方法。

Function.prototype.myCall = function(context,...args){//绑定并执行
                //执行函数
              var fn = this;
              context.fn = fn;
              context.fn(...args);
              delete context.fn
          }

          Function.prototype.myBind = function(context){//绑定返回新的执行函数
            //判断调用者是否是函数
            if(typeof this != 'function'){
                throw new Error("Error")
            }
            //截取传递的参数
            let args = [...arguments].slice(1);
            var _this = this;//保存一下当前的调用者  
            return function F() {
              return _this.apply(context,args.concat([...arguments]))
            }
          }

7.什么是深、浅拷贝,请写出代码

答:浅拷贝,就是复制一个对象,当对象的属性值没有引用类型的时候。

Object.assign 迭代(for..in for..of object.enteries) 扩展运算符等。

反之若是对象中还有引用类型,连着引用类型一并拷贝称为深拷贝。

JSON对象的方法(会忽略到值为函数和null的属性),递归。
function deepCopy(obj){
              //判断对象的类型
            var newObj =  Array.isArray(obj)?[]:{};
            if(obj && typeof obj == "object"){
                  //迭代
                  for(var key in obj){
                        if(typeof obj[key] == 'obj'){
                          newObj[key] = deepCopy(obj[key])
                        }else{
                          newObj[key]  = obj[key]
                        }     
                  }
            }
            return newObj
    }

八、什么是Ajax,如何封装一个Ajax?Get请求与 Post请求的区别?

答:Ajax的全称是异步的js与xml技术,经过它与后台服务器进行数据交换,可使网页实现异步更新,言外之意是在不从新加载整个页面的状况下,对网页进行局部更新。

1.nex xmlhttprequset对象
     2.open(method,url,false)
     3.绑定redaystatechange事件
     4.调用send方法,若是是post请求,能够传递参数

前端的请求方式除了经常使用Get和Post,还有update,delete,put等(restful api设计)
GET 请求可被缓存,保留在浏览器历史记录中 ,请求的参数是直接跟在URL上,所以不该传递敏感数据。
GET 请求有长度限制(2048字符),IE和Safari浏览器限制2k;Opera限制4k;Firefox,Chrome限制8k 。
GET 请求一般只应当用于从后台获取数据。

POST 请求不会被缓存,不会保留在浏览器历史记录中
POST 请求对数据长度没有要求。
POST 请求一般用于日后台提交数据。

9.说一些ES六、ES7新特性。

答: let,count快级做用域;解构,从对象和数组中提取值;箭头函数;字符串模版;扩展运算符...;对象的简写;module;promise(async);class;对原生对象的扩展(新增长了不少方法) ;for-of (Object.keys,values,entries等);Symbal();

不经常使用的proxy,reflect,generate函数

十、什么是Promise对象,如何使用?

答:Promise是解决异步回调的ES语法的标准,一般用来解决异步嵌套和多异步同时完成回调等问题。

Promise是一个构造函数,至关于一个容器,把异步代码包裹在里面,promise有三个状态(pending(进行中)、fulfilled(已成功)和rejected(已失败))初始化为pending,当异步请求成功后调用resolve函数,状态从pending--->fulfilled,失败的时候调用reject,状态从pending--->rejected。状态不可逆。
  缺点:书写麻烦,不能实现异步代码,同步执行的需求(配合async函数使用便可)

十一、什么是跨域,解决跨域经常使用的方式有哪些?

答:跨域是浏览器端行为,根据同源策略,当请求的协议、域名、端口只有一个不一样,就会跨域,跨域是浏览器为了安全存在的机制,浏览器会把跨域请求的数据去掉,同行报错。

在实际开发不免会出现跨域的状况,解决方案一般有

1.JSONP技术,利用了script的src属性没有跨域限制
2.CORS,当在相应头信息中添加access-control-allow-origain属性,浏览器读取到就会容许返回数据。后台配置,或者下一个浏览器插件便可。
3.后台代理(Node)
4.Iframe域的提高(不多)

十二、什么是函数的防抖、节流,并手写基本代码

答:防抖和节流都是为了提高运行效率,减小函数的执行次数。

防抖:把屡次函数执行,合并成一次执行
function debounce(fn,delay){ //fn真正执行的函数,delay间隔时间
                var timer = null;
                 return function(){
                    var args = arguments;
                    var that = this;
                    if(timer) clearTimeout(timer)
                    timer = setTimeout(function(){
                        fn.apply(that,[...arguments])
                    },delay)
                 }

       }

节流 :规定一个单位时间,在单位时间内触发一个事件回调,触发时超过间隔时间则执行,不然不执行。

function throttle(fn,gapTime){
          let _lastTime = null;
          return function(){
            var that = this;
            var args = arguments;
            let _nowTime = + new Date();
            if(_nowTime-_lastTime > gapTime || !_lastTime){
               fn.apply(that,args);
               _lastTime = _nowTime;
            }
          }
     }

1三、什么事件循环(Event Loop)?

答:js是非阻塞单线程语言,js在执行过程当中会产生执行环境,执行环境会被顺序的加入到执行栈,当遇到异步任务,会添加到task队列当中,执行同步栈,当同步栈执行完之后,event loop 就会从异步task队列当中提取要执行的代码放到执行栈中。这个一个过程称为事件循环。因此JS的异步仍是同步过程。

console.log('script start')

          setTimeout(function() {
            console.log('setTimeout')
          }, 0)

          new Promise(resolve => {
            console.log('Promise')
            resolve()
          })
            .then(function() {
              console.log('promise1')
            })
            .then(function() {
              console.log('promise2')
            })

          console.log('script end')
          //输出结果?

1五、前端安全你有了解吗?什么是XSS攻击和CSRF 跨站请求伪造?怎么预防?

答:前端的安全问题,在工做过程当中会注意这些问题。

一、XSS 代码注入问题,一般不信任用户的输入,转义输入输出内容()encodeURIComponent),括号 尖括号等。利用用户对站点的信任

   二、CSRF 跨站请求伪造 
            是一种挟制用户在当前已登陆的web应用中执行非本意的攻击
            大白话:利用用户登陆态发起恶意请求
            网站对用户的信任

添加验证码(体验稍微差一些),不让第三方访问cookie 对cookie设置 samesite, 请求验证 加 token ,

三、密码问题:对密码进行加密(MD5等)

16.如何处理精度丢失问题?

答:产生的缘由:JS使用Number类型表示一个数字,使用64位。
在这里插入图片描述

计算机先把10进制转位2进制,0.1和0.2转成二进制的时候还会无限循环,因为有51位位数的限制,多余的会被裁掉,因此在进制之间转换就会丢掉精度。
一般能够把小数乘以倍数转成正整数,计算完后再转回去。
parseFloat((0.1 + 0.2).toFixed(10))

16.前端经常使用请求数据的方式有哪些,并说出各自的区别。

答:前端进行网络请求经常使用的form,Ajax,fetch

经常使用的库文件Jquery或者axios等。
  
  Form提交数据页面会刷新,使用体验不佳。
  Ajax是一个综合技术,能够实现异步更新页面内容。使用起来方便,一般使用JQ的封装,会额外的JS加载代价。
  Fetch是新的API,比较底层。目前浏览器兼容性问题多一些,好比老版本不会携带cookie,不能直接传递JS对象做为参数,不支持JSONP等

17.如何检测一个对象必定是数组?

答:一、Object.prototype.toString.call(),前提是toString方式没有被重写。
二、instanceof 内部机制是经过判断对象的原型链中是否是能找到类型的 prototype。
[] instanceof Object; // true
三、Array.isArray() ES5新增的方法,兼容性稍微差一些。

18.JS加载会阻塞页面渲染吗?会的话该怎么解决呢?

答:会

defer:并行下载,在页面解析完后执行,会按照script的顺序执行。(经常使用)

async:异步下载代码,下载完毕后离职执行代码,不会按照页面的script顺序。

20.常见前端性能优化有哪些?
答:
1:加载优化

CDN,文件压缩混淆合并,按需加载(异步组件),前端缓存,浏览器缓存(cache-control,exprices) 
     
     DNS预先解析,服务器渲染 nuxt,next(SEO),图片懒加载

2:脚本优化

减小合并DOM操做(createDocumentFragment),CSS3代替js动画,缓存变量,用requestAnimationFrame代理setTimeout,减小reflow与repain,事件代理,开启GPU渲染tranfrom:translateX(0)

3:图片优化

雪碧图(减小请求),使用SVG和iconfont(字体图片)代替图片,图片压缩

更多前端面试相关和性能优化前端自动化测试视频教程请私信或点击获取。

相关文章
相关标签/搜索