前端笔试题

第一题

<script>
      var a = 10;
      function test() {
            a = 100;
            console.log(a);      //100
            console.log(this.a)  //10
            var a;
            console.log(a)       //100
      }      
      test()     

      // 解题思路 :  变量提升   函数调用模式的this指向window 
</script>

第二题

<script>
      for(var i=1; i<10; i++){
            setTimeout(function(){
                  console.log(i)
            },1000)
      }
      // 输出9遍 10 

for(let i=1; i<10; i++){ setTimeout(function(){ console.log(i) },1000) } // 输出 1,2,3,4,5,6,7,8,9 </script>

第三题

<script>
      // 输出结果?
       var arr = [1,3,4,5,65,6]
       arr.forEach( i=>{
             console.log(i);
             if(i==5){
                  return 
             }
       })
      //  输出结果 1,3,4,5,65,6   
</script>

第四题

      什么是MVVM,常用的MVVM框架有哪些?
      M 表示model 模型 data中的内容   页面中所需的数据
      V 表示view  视图 模板中内容     html+css 静态页面
      vM 表示viewModel 视图模型,建立连接,实现双向绑定
      模型数据改变,视图自动更新;视图数据改名,模型数据自动更新
      vue react angular
 

      什么是MVC?
      M  model  模型
      V  view   视图
      C  controller  控制器  需要手动操作大量的DOM,数据是单向传送的

第五题

<script>
// 已知有以下数组,请将数组随机乱序
  let arr = [1,2,3,4,5]

// 方法一
  let newArr=[]
  for(let i = 0; i < Infinity; i++){
        if(newArr.length==5){// 如果 newArr 和 arr原始数组的长度一样,跳出循环
            break
        }
        let index = Math.floor( Math.random() * arr.length )   //随机获取数组下标
        newArr.push(arr[index])   // 将随机出来的元素添加到newArr中 
        arr.splice(index,1)       //删除添加过的元素 
  }
  console.log(newArr)

</script>
<script>
// 已知有以下数组,请将数组随机乱序
  let arr = [1,2,3,4,5]

// 方法二
  let newArr=[]
  for(let i = 0; i < arr.length; i++){
        let index = Math.floor( Math.random() * arr.length )   //随机获取数组下标
        newArr.push(arr[index])   // 将随机出来的元素添加到newArr中 
        arr.splice(index,1)       //删除添加过的元素 
  }
  var result = new Set( [ ...arr , ...newArr ] )
  console.log([...result])

</script>

第六题

      npm init 和 npm install vue 区别? 如何安装指定版本的js模块?
      npm init 是初始化项目,使用后会多出一个 package.json 的文件
      npm install vue 是安装vue
      使用 @ 可以指定版本 比如: npm i  jquery@3.0.0 

      全局安装?
      npm install xxx -g  //模块将被下载安装到【全局目录】中

      本地安装?
      npm install xxx //则是将模块下载到当前命令行所在目录

      信息写入?(安装的同时,将信息写入package.json中项目路径中)
      npm install xxx --save
      npm install xxx --save-dev  
      
      --save 将依赖包名称添加到 package.json 文件 dependencies 键下  (发布后依赖的东西)
      --save-dev 则添加到 package.json 文件 devDependencies 键下    (开房时候依赖的东西)

      --save 是你发布之后还依赖的东西
      --save-dev 是你开发时候依赖的东西

第七题

如何实现单页面同时适应  pc 和 移动端设备 ?
      @media 媒体查询
      /* 当屏幕小于等于100px的时候背景色为红色 */
@media screen and (max- 100px) {
    .example {background: red;}
}

/* 当屏幕在 200px -- 300px 的时候背景色为绿色 */
@media  screen and (min- 200px) and (max- 300px) {
    .example {background: green;}
}

 或者使用bootstrap中的媒体查询

第八题

vue中如何防止卡白屏?

原因? vue项目完成后一打包,js都放到了一起,由于js太庞大,加载变慢出现白屏(app.js太大)

解决?

当打包构建应用时,JavaScript 包会变得非常大,影响页面加载。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应组件,这样就更加高效了。

使用路由懒加载,可以将js分别打包到不同的文件中。

使用骨架屏(vant)

 01  配置打包工具,将组件分别打包到不同的js代码块中

    biuld/weabpack.base.conf.js

        output:{

          chunkFilename:"[   ]"   //为了懒加载新增,配置后webpack将打包出多个js文件  

          }

    02  当路由请求到该组件时,才动态加载组件的内容

       引入组件时要改为

      import index from './'xxx  改为    const index=()=>import ('./xxx')  仅定义函数  不执行

      当用户在vue中请求当前组件对应的路由地址时,由vue-router自动调用加载函数

第九题

简单描述一下前端优化的理解?

css放顶部,js放底部

精灵图,字体图标

压缩代码

前端你的优化在于减少DOM的操作和减少页面的重排重绘

第十题

call和apply的区别是什么?哪个性能更好一点?

call传参是一个一个传入  fn.call( obj , 10,20,30)

apply传参要用数组的形式[ ]   fn.apply( obj , [10,20,30] )

传参多的时候,call的性能要比apply稍好些。所以call的性能要优于apply,所以在开发时候,使用call,如果传入的参数是数组,可以使用...展开用算符传参  fn.call( obj , ...arry )

  

第十一题

代码性能测试 console.time('a')   console.timeEnd('a')

测试代码运行时间可以使用 console.time和console.timeEnd 来测试一段代码运行的时间 (火狐浏览器可以使用console.profile进行测试)
 
<script>

// 测试代码运行时间可以使用 console.time和console.timeEnd 来测试一段代码运行的时间
console.time('A')
for( let i=1 ; i<100; i++){

}
console.timeEnd('A')

// 输出结果:    A: 0.007080078125ms
     
</script>

第十二题

 实现 (5).add(3).minus(2) ,使其结果输出为6  

      如何实现 实例调取方法?  如何实现链式写法?
      想实现实例调取方法,只需要将方法 放到  当前实例所属类的原型上(比如数字实例要放到 Number上)
      想实现链式写法,就让当前方法执行完的返回结果还是当前这个类的实例,这样就可以继续调用其他方法了
<script>
/*
      arr.push()  arr数组之所以可以调用数组方法, 是因为 arr是Array的实例,可以调用Array.prototype 原型上的方法。push就是Array的方法

      jq源码中:给原型上添加方法
      ['add','minus'].forEach( elem=>{
            Number.prototype[elem] = eval(elem)
      })
*/


      //   5   +   3    -  2       =   6
// 实现 (5).add(3).minus(2) ,使其结果输出为6  
(function(){

      function check(n) {
            n = Number(n)
            return isNaN(n) ? 0 : n ; // 如果是NAN返回0 否则返回n
      }

      // 每一个方法执行完,都要返回Number这个类的实例,这样才可以继续调用Number类原型中的方法(链式写法)
      function add(n=0){
            n = check(n)
            return this + n;   //this指向5 ; 
      }

      function minus(n=0){
            n = check(n)
            return this - n;
      }

      Number.prototype.add=add;  //将add函数添加到原型中
      Number.prototype.minus=minus;//将minus函数添加到原型中

}());
console.log(  (5).add(3).minus(2) ) //  6

  
</script>

十三题

什么是回调函数:把一个函数B作为实参传递给另外一个函数A;函数A在执行的时候,可以把传递进来的函数B去执行(执行N次数)

function each(arr,callBack) {
      for( let i= 0; i < arr.length; i++){
            let item = arr[i];
            index = i;
            callBack( item , index )
      }
}
each( [1,2,3,4], function( item, index) { } )

十四题

      箭头函数和普通函数的区别是什么? 构造函数可以使用new生成实例,那么箭头函数可以吗?为什么?
箭头函数和普通函数的区别?
      01 箭头函数语法上比普通函数更简洁
      02 箭头函数没有自己的this,它里面的this继承函数所处上下文中的this(箭头函数中的this与外层函数的this一致)
         箭头函数中的this,使用call/apply等任何方式都无法改变this的指向(都和外层函数this一致)
      03 箭头函数中没有 arguments(类数组)
      04 箭头函数不能被new执行(普通函数 可以写成构造函数格式),为什么?因为箭头函数中没有this,箭头函数没有prototype
         箭头函数时没有this,也没有prototype,也没有arguments

十五题

      console.log(a) //undefined
      var a = 12;
      function fn () {
            console.log(a); // 12
             a = 13;
      }
      fn();
      console.log(a); //13

十六题 

axios和ajax的区别?

    axios是基于promise的专门发送ajax请求的函数库,通过promise实现对ajax的封装。自动转换JSON数据

              ajax是针对mvc的编程,不符合mvvm模式的开发

$.ajax({
            url: '/getUsers',
            type: 'get',
            dataType: 'json',
            data: {
                //'a': 1,
                //'b': 2,
            },
            success: function (response) {
                console.log(response);
            }
        })
<script>


axios.get("url",{

  params:{

    请求参数: 参数值

  }

}).then(function(返回结果result){

  result.data    //才是服务器返回的结果

})


// 比如: 用id查询一个商品
//http://localhost:3000/products/getById?lid=5  ->

//  { lid:5, title: macbook, subtitle: 优惠酬宾, ... } <-

axios.get("/products/getById",{

  params:{

    lid:5

  }

})

.then(function(result){

  var product=result.data;

})

</script>

十七题 

js事件机制?  

    捕获   目标触发   冒泡

十八题

浏览器的缓存问题?

当浏览器请求一个网站的时候,会加载各种各样的资源,比如HTML文档、图片、CSSJS等文件。对于一些不经常变的内容,浏览器会将他们保存在本地的文件中,下次访问相同网站的时候,直接加载这些资源,加速访问。

这些被浏览器保存的文件就被称为缓存。(不是指Cookie或者Localstorage)。

解决方法  : 

ctrl + f5:强制刷新

遇到图片缓存问题,可以在请求的url路径后加 ?new Date()

十八题

js如何区分数组和对象?

<script>

console.log( {}.constructor  ) // Object
console.log( [].constructor  ) // Array



console.log(  {} instanceof Array   ) //false
console.log(  [] instanceof Array   ) // true



console.log(  Array.isArray({})   ) //false
console.log(  Array.isArray([])  ) // true

console.log( toString.call( {} ) ) //[object Object]
console.log( toString.call( [] ) ) //[object Array]
</script>

十九题

<script>
      var User = {
            count : 1,
            getCount : function () {
                  return this.count
            }
        }
        console.log(User.getCount())  //  1
        var func = User.getCount;
        console.log( func() )   // undefined
</script>

二十题

      for ( var i = 1; i <= 3; i++){
            setTimeout (function () {
                  console.log(i) // 三个 4
            },0)
      }

二十一题

<script>
      var name = 'jack';
      function change () {
            alert(name);    //undefinded
            var name = 'lily'
            alert(name)     // lily
      }
      change();
</script>

二十二题

javascrip是如何继承的?

    原型链继承方式  或者 借用构造函数(使用call/apply)

 
      http状态码403表示的含义? 
      A Bad gateway
      B Bad Request  请求参数不对
      C Unauthorized 
      D Forbidden   //403 禁止请求
 
  • 200 - 请求成功
  • 301 - 资源(网页等)被永久转移到其它URL
  • 404 - 请求的资源(网页等)不存在
  • 500 - 内部服务器错误

二十三题

<script>
      setTimeout(() => {
            console.log('setTimeout')
      }, 0);     
      let p1 = new Promise( (resolve)=>{
            console.log('promise1')
            resolve('promise2')
      } )
      p1.then( (res)=>{
            console.log(res)
      })
      console.log(1)
      // 打印结果是?
      //  promise1  1 promise2 setTimeout
</script>

二十四题

vue中二级联动怎么做?

使用嵌套路由

router-view     vue-router的配置,使用children[ ]

二十五题

      // Object.keys(arr)  中放入数组,会以字符串的形式,返回所有数组的下标   输出的是[]格式
      var arr = ['z','h','y']
      console.log(  Object.keys(arr) )   //["0", "1", "2"]

      // Object.keys(arr)  中放入对象,会以字符串的形式,返回所有对象中的属性名  输出的是[]格式  
      var obj = {
            name:'zh',
            age:18,
            money:9999999999
      }
      console.log(  Object.keys(obj) ) //["name", "age", "money"]
      // 输出对象中值大于2的key的数组
      var data = {a:1,b:2,c:3,d:4}    
      // ['a','b','c','d']
      var result = Object.keys(data).filter(function(k){
            return k!='a'&&k!='b'
      })
      console.log(result)
      // 期待输出 ['c' , 'd']

二十六题

<script>
      (function(){
            var a=b=5;  //  b=5;
      })();             //  var a = b;
      console.log(b) // 5
      console.log(a) // a is not defined
</script>

 二十七题

http与https,运营商注入问题

HTTP(超文本传输协议)被用于在Web浏览器和网站服务器之间,以明文方式传递信息,不提供任何方式的数据加密,因此使用HTTP协议传输隐私信息(如:银行卡号、密码等支付信息)非常不安全。 数据可以被劫持注入广告

HTTPS协议="SSL+HTTP协议"构建的可进行加密传输、身份认证的网络协议,是HTTP的安全版。

 

二十八题

浏览器渲染机制,渲染引擎以及js引擎

    V8引擎是?  js引擎  负责执行js代码

    渲染引擎?  负责执行 html  css  等代码

二十九题

      var  foo = 1;
      function bar () {
            if(!foo){  //变量提升   !undefined  
                  var foo = 10;
            }
            console.log(foo)  // 10
      }
      bar();

三十题

<script>
      var n = 0;
      function a () {
            var n = 10;
            function b () {
                  n++;
                  console.log(n);  
            }
            b();  // 11
            return b;
      }
      var c = a();
      c(); // 12
      console.log(n)   //  0
      // 输出 :  11  12  0
</script>

三十一

<script>
      var a = 10,b=11,c=12;
      function fn (a) {
            a = 1;
            var b = 2;
            c = 3;
      }
      fn(10); // 传入实参 10 ,就相当于在函数中var a = 10
      console.log(a);//10
      console.log(b);//11
      console.log(c);//3
</script>

三十二题

<script>
      // in: 检测某一个属性是否属于这个对象(不管是私有属性还是公有属性)
// hasOwnProperty:检测某一个属性是否为对象的私有属性(只有私有的属性才可以)  

if(!('a' in window)){// window中 有没有 a var a = 1; } console.log(a)//undefined // 解题思路: 因为变量提升,var a 提升到最前边,全局中有了a,所以 'a' in window 是true </script>

 三十三题

      var a = 9;
      function fn () {
            a = 0;
            return function (b) {
                  return b+a++;
            }
      }  
      var f = fn();
      console.log( f(5) )  // 5
      console.log( fn()(5) )  // 5
      console.log( f(5) )  // 6
      console.log( a ) // 2

 三十三题

      var arry = [1,2,3,4]; // arry = aaafff000 ([1,2,3,4]) 地址
      function fn (arry) {//aaafff000       arry = aaafff000
            arry[0]=0; // [0,2,3,4]
            arry=[0];  // [0] 创建了一个新地址 bbbfff000, arry=bbbfff000   引用值:[0]   
            arry[0]=100;  // bbbfff000[0]=100  , 引用值 :[100]
            return arry   //  [100]
      }
      var res = fn(arry) //[100]
      console.log(arry)  // 输出 [0,2,3,4]
      console.log(res)   // 输出 [100]

三十三题

      function fn (i) {
            return function (n) {
                  console.log( n + (i++) );
            }
      }
      var f = fn(10);
      f(20);  //30
      fn(20)(40); // 60
      fn(30)(50); // 80
      f(30)       // 41

三十四题

<script>
      var i = 10;
      function fn () {
            return function (n) {
                  console.log( n + (++i) );
            }
      }
      var f = fn();
      f(20);     //31  
      fn()(20);  //32
      fn()(30);  //43
      f(30)      //44
</script>
    <!-- 解题思路: 匿名函数自调中的this  指向 window 
             方法调用中的this指向.前的对象 -->
<script>
      var num = 10;
      var obj = { num:20 }
      obj.fn = (function (num) {
            this.num = num * 3
            num++;
            return function (n) {
                  this.num += n
                  num++
                  console.log(num)
            }
      })(obj.num)
      var fn = obj.fn 
      fn(5);//22
      obj.fn(10);//23
      console.log(num,obj.num) //65   30
</script>
    <!-- 解题思路: 匿名函数自调中的this  指向 window 
             方法调用中的this指向.前的对象 -->
<script>
      var num = 10;
      var obj = { num:20 }
      obj.fn = (function (num) {
            num = this.num + 10;
            this.num = num + 10;
            return function () {
                  this.num += num
            }
      })(num)
      var fn = obj.fn 
      fn();
      obj.fn();
     console.log(num,obj.num) //50   40
</script>

 三十五题

      <!-- 解题思路:元素绑定事件,方法中的this是当前操作的元素
                    方法名前面是否有点,有点,点前面是谁this就是谁,没有.this是window(严格模式下是undefined)
                    构造函数执行,方法体中的this指向向new出来的对象
      -->
<script>
      var fullName = 'language';
      var obj = {
            fullName : 'javascript',
            prop:{
                  getFullName:function (){
                        return this.fullName
                  }
            }
      }
      console.log(obj.prop.getFullName()); //undefined
      var test = obj.prop.getFullName;
      console.log( test() ) //language

三十六题

      <!-- 解题思路:new做的四件事
                    创建一个新的对象
                    调用函数
                    改变this指向
                    返回一个新的对象
            查找规则:先从自己身上找,如果找不到再去原型上找     
      -->
<script>
      function fun () {
            this.a=0;
            this.b=function () {
                  alert(this.a)
            }
      }
      fun.prototype = {
            b:function (){
                  this.a = 20
                  alert(this.a)
            },
            c:function (){
                  this.a=30
                  alert(this.a)
            }
      }
      var my_fun = new fun();//新对象
      my_fun.b();//  alert 0
      my_fun.c();//  alert 30

</script>

    

三十七题

<script>
      function Fn () {
            var n = 10;
            this.m = 20;
            this.aa = function () {
                  console.log(this.m)
            }
      }
      Fn.prototype.bb = function () {
            console.log( this.n )
      }
      var f1 = new Fn;
      Fn.prototype = {
            aa:function () {
                  console.log(this.m+10)
            }
      }
      var f2 = new Fn;
      console.log( f1.constructor )  // Fn
      console.log( f2.constructor )  // Object
      f1.bb()                        // undefined
      f1.aa()                        // 20
      // f2.bb()                        //报错
      f2.aa()                        //20
      f2.__proto__.aa()              //NaN
</script>

三十八题

      //依次遍历数组中的每一项,让每一项的值作为对象的属性名和属性值(属性值存什么都可以),每一次存储之前验证当前对象中是否已经存在这个属性了(in/hasOwnProperty/属性值不是undefined),
如果有这个属性了,说明当前项在数组中已经存在了,我们把当前项在原有数组中移除,如果不存在,存储到对象中即可
var ary = [1,1,1,1,1,2] function unique (ary) { var obj = {}; for ( var i = 0; i < ary.length; i++){ /* 优化:不使用splice删除(删除当前项,后面索引移动位置,如果后边有很多项,到性能消耗大) 解决:把最后一项替换当前项,删除最后一项即可(会改变原有数组的排序) */ var item = ary[i] if( obj.hasOwnProperty(item) ){//如果元素已经存在 ary[i] = ary[ary.length-1];// 当前项 = 最后一个元素 ary.pop() i-- continue; } obj[item]=item; } obj = null ; //优化:obj没有之后手动释放一下,节约内存 return ary } console.log( unique(ary) ) //[1, 2]

终极优化版

<script>
/*
       用对象键值对的方式来减少双for循环带来的循环次数过多,性能消耗
       对象键值对里解决数组塌陷问题
       删除数组元素,导致数组索引位移问题
       手动释放堆内存
       把方法扩展到内置类的原型上
*/

    var ary =  [1,1,2,2,3,4,5] 
    Array.prototype.my_unique = function my_unique () {
             var obj = {};
             for ( var i = 0; i<this.length; i++) {//this 指向方法.前的对象ary
                  var item = this[i]
                  obj.hasOwnProperty(item)?(this[i]=this[this.length-1],this.pop(),i--):obj[item]=item
             }        //判断对象obj中是否有item元素,如果有 让当前元素等于数组最后一个元素,删除最后一个元素
                      //                           如果没有   将这个元素添加到对象中
             this.sort((a,b)=>{return a-b})// 数组去重后 按升序排列
             obj = null;
    }
    ary.my_unique()
    console.log(ary) // [1, 2, 3, 4, 5]
</script>

三十九题 

   document.parentNode 和 document.parentnode 区别?
      document.parentNode 文档的父节点,文档已经是最外层了
      document.parentNode ---- null  , 有这个属性,值是null
      document.parentnode ---- undefined , 没有这个属性,未定义

三十九题

怎么规避多人开发函数重名的问题?
      闭包  组件化 模块化开发
 
 
四十题
 javaScript如何实现面向对象中的继承?
      原型继承
      call/apply继承
      class继承
 
 四十一题
(function(x){
      delete x
      alert(x)
})(5+1)
// 输出结果: 是 弹出 6

四十二题目

/*
实现一个$attr(name,vlaue)
属性为 name
值为value的元素集合
*/
<!DOCTYPE html>
<html lang="en">
<head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <meta http-equiv="X-UA-Compatible" content="ie=edge">
      <title>Document</title>
</head>
<body>
<div name='AA' class="box clearfix"></div>
<div class="content box"></div>
<div name='BB'></div>
<div id="AA"></div>
<div class="box"></div>
<div name='BB'></div>
<div name='AA' class="box clearfix"></div>

<script>

let ary = $attr('name','box'); // 获取页面中所有name为box的元素

// 思路:获得页面中所有的标签,循环得到每一个标签 
function $attr(property,vlaue) {
      // 获取当前页面中所有的标签
      let elements = document.getElementsByTagName('*');
      elements = Array.from(elements)// 将elements变为数组
      console.log(elements instanceof Array)
      arr = [];
      [].forEach.call(elements,function(item){
            // 存储的是当前的元素property对应的属性值
            let itemValue = item.getAttribute(property)
            if(property==='class'){
                  // 样式类属性名要特殊的处理
            new RegExp("\b"+vlaue+"\b").test(itemValue)? arr.push(item):null;
            return
            }
            if(itemValue === vlaue){
                  arr.push(item)
            }
      })
      return arr

}

console.log($attr('name','AA') )


</script>  
</body>
</html>

四十三题

<script>
      let str = '你好,word哈哈哈aaa不错'
      reg = /[a-z]+/
      str=str.replace(reg,(item)=>{
            return ' ' + item + ' '
      }).trim()
      console.log(str);  // 你好, word 哈哈哈aaa不错
</script> 

四十四题目 

数组扁平化(可以通过es6的flat   或者  数组.toString()转为对象,再split(',')转回数组)

<script>
// 编写一个程序,将数组扁平化,并去除其中重复部分数据,最终得到一个升序且不重复的数组
let arr = [[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,14]]],10]
// 使用es6中提供的Array.prototype.flat 处理  将数组扁平化
arr=arr.flat(Infinity)
var result = new Set(arr)
result = [...result].sort((a,b)=>{return a-b})
console.log(result);

</script> 
 四十五题目
 
<script>
// 编写一个程序,将数组扁平化,并去除其中重复部分数据,最终得到一个升序且不重复的数组 let arr = [[1,2,2],[3,4,5,5],[6,7,8,9,[11,12,[12,13,14]]],10] // 使用es6中提供的Array.prototype.flat 处理 将数组扁平化 arr=arr.toString().split(',').map((item)=>{ return Number(item) }).sort((a,b)=>{return a-b}) console.log(arr) </script>
 
原文地址:https://www.cnblogs.com/javascript9527/p/11484093.html