让前端飞Web前端之路

前端面试题

2020-04-06  本文已影响0人  穆熙沐

1,遍历

        let arr = [1,2,3];
        arr.name = 'a';
        Array.prototype.sex = "ds";
        console.log(arr);//[1,2,3,name:'a']
        for(var i=0;i<arr.length;i++) {
            console.log(arr[i]) //1,2,3
        }
      //可以遍历对象和数组
        for(var key in arr) { 
            console.log(key)//0,1,2,name,sex (hasOwnproperty)
        }
       console.log(Object.keys(arr));//['0','1','2','name']
      //只能数组
        for(var key of arr) {
            console.log(key)//1,2,3
        }
      //只能数组
        arr.forEach(i => {
            console.log(i) //1,2,3
        })

2, 逻辑运算符
1 && 2 若 1 可转换为 true,则返回 2;否则,返回 1。
1 || 2 若 1 可转换为 true,则返回 1;否则,返回 2。
可以转为false:
null;NaN;0;空字符串("" or '' or ``);undefined

        alert(1 && 2); //2
        alert(0 && 2); //0
        alert(0 && undefined); //0
        alert(1 || 2); //1
        alert(0 || 2); //2
        alert(0 || undefined); //undefined

3,闭包

       for(var i=10;i>0;i--) {
            (function(k){
                setTimeout(function() {
                    console.log(k); //10,9,8,7
                }, 0)
            })(i)
        } 

4,变量提升

       (function() {
            console.log(name);//报错且终止运行。 在初始化之前未能Cannot access 'name' before initialization
            console.log(age);//如果在报错之前的话可以输出undefined
            let name = 's';
            var age = 14;
        })()

5,数字属性名==变量属性名的时候,

  1. 后者覆盖前者
        let a={},b='0',c=0;
        a[b]='超逸';
        a[c]='博客';
        console.log(a[b]); //博客

2)symbol声明唯一值

    let a = {},b = Symbol('0'),c = Symbol(0);
        a[c] = '博客';
        a[b] = '超逸';
        console.log(a[c]);//博客
对象属性名还可以是symbol.png

6, 多层嵌套深拷贝

       function isArray(val) {
            return Object.prototype.toString.call(val) === ['Object Array'];
        }
        function isObject(val) {
            return typeof val === 'Object' && typeof val !== null;
            //注意: typeof null/[]/{} === 'Object'; 
        }
        function DeepClone(val) {
            var obj = isArray(val) ? [] : {};
            for (var key in val) {
                if (isObject(val[key])) {
                    obj[key] = DeepClone(val[key]);//递归
                } else {
                    obj[key] = val[key];
                }
            }
            return obj;
        }

7: 综合

       function Foo(){
            getName=function(){
                console.log(1);
            };
            return this;
        }
        Foo.getName = function (){
            console.log(2);
        };
        Foo.prototype.getName = function (){
            console.log(3);
        };
        var getName = function(){
            console.log(4);
        };

        function getName(){
            console.log(5);
        }

        Foo.getName();//2
        getName();//4
        Foo().getName();//1
        getName();//1
        new Foo.getName();//4 先Foo.getName() 无参数new
        new Foo().getName();//3 先new Foo()实例,然后找构造函数原型上的getName
        new new Foo().getName();//3

8,浏览器是多线程的,而js是单线程的

      async function async1(){
            console.log('async1 start');
            await async2();
            console.log('async1 end');
        }
        async function async2(){
            console.log('async2');
        }
        console.log('script start');
        setTimeout(function(){
            console.log('setTimeout');
        },0)
        async1();
        new Promise(function (resolve){
            console.log('promise1');
            resolve();
        }).then(function(){
            console.log('promise2');
        });
        console.log('script end');
script start ----async1 start ---async2
 ---- promise1(同步执行立即执行) -- script end ---- async1 end ---promise2(微任务)----settimeout(宏任务)

9,多维数组拉平

arr = [1, 2, [3, 4, [5, 6, [7, 8]]]].join(',').split(',');
//["1", "2", "3", "4", "5", "6", "7", "8"]
arr =  [1, 2, [3, 4, [5, 6, [7, 8]]]].flat(Infinity) ;
//es6方法 [1, 2, 3, 4, 5, 6, 7, 8]

10,父子组件执行顺序:


image.png

11,块级作用域 let const 定义的不是顶层对象

       const a = {
            b: function(){console.log(this)},
            c: ()=>{console.log(this);}
        };
        a.b(); //a
        a.c(); //window
        console.log(window.a);//undefined

        let a = 'ss'; 等价于
       { 
          let a = 'ss'
          }

12,js实现es6数组方法
filter:

      Array.prototype.filter1 = function(fn) {
            console.log(this);//谁调用就是谁 [1,2,3,4]
            var arr = [];
            // 遍历数组,回调函数为true 就返回
            this.forEach(i => {
                if (fn(i)) {
                    arr.push(i);
                }
            })
            return arr;
            
        }
        console.log([1,2,3,4].filter1(item => {return item > 2;}));//[3,4]

every:

        Array.prototype.every1 = function(fn) {
            console.log(this);//谁调用就是谁 [1,2,3,4]
            var arr = [];
            // 遍历数组,回调函数为true 就返回
            this.forEach(i => {
                if (fn(i)) {
                    arr.push(i);
                }
            })
            // 每一个都符合条件
            return arr.length === this.length;
            
        }
        console.log([1,2,3,4].every1(item => {return item > 2;}));//false

some:

        Array.prototype.some1 = function(fn) {
            console.log(this);//谁调用就是谁 [1,2,3,4]
            var arr = [];
            // 遍历数组,回调函数为true 就返回
            this.forEach(i => {
                if (fn(i)) {
                    arr.push(i);
                }
            })
            // 至少有一个
            return arr.length > 0;
            
        }
        console.log([1,2,3,4].some1(item => {return item > 2;}));//true

map:

        Array.prototype.map1 = function(fn) {
            console.log(this);//谁调用就是谁 [1,2,3,4]
            var arr = [];
            // 遍历数组,回调函数返回结果放到新数组
            this.forEach(i => {
                arr.push(fn(i));
            })
            return arr;
        }
        console.log([1,2,3,4].map1(item => {return item * 2;}));//[2,4,6,8]

find:

        Array.prototype.find1 = function(fn) {
            console.log(this);//谁调用就是谁 [1,2,3,4]
            // 遍历数组,回调函数为真返回第一个元素并跳出循环
            for(var i=0; i<this.length;i++) {
                if(fn(this[i])) {
                    return this[i];
                }
            }   
        }
        console.log([{a: 1,b: 2},{a: 111,b:222}, {a: 111, b:2}].find1(item => {return item.a === 111;}))//{a: 111,b:222}

13,意外全局变量

      function foo() {
            let a = b = 0;
            a++;
            return a;
        }
        foo();
        console.log(typeof a); //undefind
        console.log(typeof b, b); //number 0

14,length修改数组

       const a = [1,2,3];
        a.length = 0;
        console.log(a[0]); //undefind

15, 块级作用域

        const a = [1,2,3];
        a = [];
        console.log(a[0]); 报错,let可以 a.push(1)可以

16, for空语句

        let arr = [], i = 0;
        for(i = 0; i < 4; i++); 
        {
            arr.push(i)
        }
        console.log(arr);//[4]

17, 折行

        function ss(item) {
            return
            [item];
        }
        console.log(ss(10));//undefind   return;[item]

18,访问地址做的事情


image.png

URI解析-----DNS解析----TCP三次握手----发送HTTP请求----服务端处理和响应----TCP四次挥手,关闭链接通道---浏览器解析渲染
19,前端优化
一)浏览器渲染解析
1,标签语义化,2,避免多级嵌套,解析快些。


image.png
2,选择器层级问题 特别长不好
image.png

3,真正渲染到页面中的时候:一定发生在DOM-Tree和CSSOM树都已经完成,已经生成render tree了才回流和重绘,HTML和css都是阻碍页面渲染的东西
4,link是发送有个HTTP请求,每一个HTTP请求都是单独线程去处理,所以dom树有时候会优先CSS。style比link好。link放前边,preload 提前加载。
5,js默认加载阻塞。放在底部
6,减少页面的回流: 少操作元素(VUE,react,)
二)DNS解析


image.png
三)缓存
image.png
20,vue过滤器:第一个参数默认是原始值。
filters: {
    myfilter (value, arg) {
      let s = value.split('')
      let n = 0
      s.forEach((elem) => {
        if (elem === arg) {
          n++
        }
      })
      return n
    }
  }

21,vue data和computed和watch区别
1.如果一个数据依赖于其他数据,那么把这个数据设计为computed的
2.如果你需要在某个数据变化时做一些事情,使用watch来观察这个数据变化。
22,vue中key的作用。
为了高效的更新虚拟DOM。
23,为什么vue中data返回一个函数。
如果两个实例同时引用一个对象,那么当你修改其中一个属性的时候,另外一个实例也会跟着改;
两个实例应该有自己各自的域才对。
24,addEventListener

button.addEventListener("click",function(){
        alert(this.id);
    },false); //false 冒泡阶段触发stopPropergation ;true: 捕获阶段触发 preventDefault

25,栈(stack)和堆(heap)


image.png

26, es6继承

     class Parent {
            constructor(name, age) {
                this.name = name;
                this.age = age;
            }
        }
        class child extends Parent {
            constructor(name, age, sex) {
                super(name, age);
                console.log(this);
                this.sex = sex; // 必须先调用super,才能使用this
            }
        }

27,防抖和节流
防抖:
动作绑定事件,动作发生后一定时间后触发事件,在这段时间内,如果该动作又发生,则重新等待一定时间再触发事件。(如果动作不停,就不会执行事件)
Input验证身份证号

 function debounce(fn) {
      let timeout = null; // 创建一个标记用来存放定时器的返回值
      return function () {
      if (timeout) {
          clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
         }
        timeout = setTimeout(() => { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(this, arguments);
          // fn(); this指向window
        }, 2000);
      };
    };
    function say() {
      console.log(this);
      console.log('say');
    };
  $('#ipt').bind('input', debounce(say));

箭头函数 apply: 改变this指向,指向的是input;


image.png

如果不是箭头函数,this指向window


image.png
解决办法: 函数外this赋值给that
  return function () {
      let that = this;
      if (timeout) {
          clearTimeout(timeout); // 每当用户输入的时候把前一个 setTimeout clear 掉
         }
        timeout = setTimeout(function() { // 然后又创建一个新的 setTimeout, 这样就能保证输入字符后的 interval 间隔内如果还有字符输入的话,就不会执行 fn 函数
          fn.apply(that, arguments);

节流:scroll事件 。。动作绑定事件,动作发生后一段时间后触发事件,在这段时间内,如果动作又发生,则无视该动作,直到事件执行完后,才能重新触发。(每隔一段时间就会执行)

function showTop  () {
    var scrollTop = document.body.scrollTop || document.documentElement.scrollTop;
  console.log('滚动条位置:' + scrollTop);//1秒才打印一次,否则会打印很多很多
}
function throttle(fn){
    let canRun = true;
    return function(){
        if(!canRun){
            return
        }
        canRun = false;
        setTimeout(() => {
            fn.apply(this, arguments);
            canRun = true;
        }, 1000)
    }
};
window.onscroll  = throttle(showTop);

28,深拷贝
遍历、递归

function deepClone(obj) {
  let result = Array.isArray(obj) ? {} : [];
  for(var key in obj) {
    if (obj.hasOwnproperty(key)) {
      if (typeof(obj[key]) === 'Object' && obj[key] !== null) {// typeof(null) === Object
        result[key] = deepClone(obj[key]); //递归,对象深层嵌套
      } else {
        result[key] = obj[key];
      }
    }
  }
}

转字符串后转对象

function deepClone(arr){
    return JSON.parse(JSON.stringify(arr))
}

29,

上一篇 下一篇

猜你喜欢

热点阅读