开发喵星球

前端JavaScript面试100问(上)

前端JavaScript面试100问(上)

1、解释一下什么是闭包 ?

2、解释一下原型和原型链 ?

原型

原型就是一个为对象实例定义了一些公共属性和公共方法的对象模板。

原型链

对象之间的继承关系通过构造函数的prototype指向父类对象,直到指向Object对象为止形成的指向链条。

通俗讲:原型链是原型对象创建过程的历史记录。

注:在javascript中,所有的对象都拥有一个__proto__属性指向该对象的原型(prototype) 。

3、说一下 ES6 中你熟悉的一些内容 ?

4、数组排序的方式 ?

   for(var i=0;i<arr.length-1;i++){
           for(var j=0;j<arr.length-i-1;j++){
               if(arr[j]>arr[j+1]){
                  var temp=arr[j];
                  arr[j]=arr[j+1];
                  arr[j+1]=temp;
              }
          }
       if(arr[j]===arr[j-1]) i++;
      }
for(var i=0;i<arr.length;i++){
          var min=i;
           for(var j=i+1;j<arr.length;j++){
               if(arr[j]<arr[min]) min=j;
          }
           if(min!==i){
              var temp=arr[i];
              arr[i]=arr[min];
              arr[min]=temp;
          }
       if(arr[i]===arr[i+1])i++;
}
function quickSort(arr) {
  if (arr.length <= 1) return arr;
  var centerIndex = ~~(arr.length / 2);
  var left = [];
  var right = [];
   for (var i = 0; i < arr.length; i++) {
       if (i === centerIndex) continue;
       if (arr[i] < arr[centerIndex]) left.push(arr[i]);
       else right.push(arr[i]);
      }
      return quickSort(left).concat(arr[centerIndex], quickSort(right));
  }

5、什么是事件轮询(EventLoop) ?

一个用来等待和发送消息和事件的程序结构。

6、数组的一些API, 哪些能够改变原数组, 那些不能 ?

shift()
unshift()
pop()
push()
reverse()
sort()
splice()
concat()
every()
filter()
forEach()
indexOf()
join()
lastIndexOf()
map()
some()
every()
slice()
reduce()
reduceRight()
flat()
flatMap()
find()

7、for 循环与 forEach 的区别 ?

8、深浅拷贝 ?

function cloneObject(source, target) {
     if (target === undefined) {
       if (Node.prototype.isPrototypeOf(source)) {
        target = document.createElement(source.nodeName);
        target.style = source.style.cssText;
      } else if (source.constructor === Uint8Array) {
        target = new source.constructor(Array.from(source));
      } else if (source.constructor === Date || source.constructor === RegExp || source.constructor === Set || source
        .constructor === Map) {
        target = new source.constructor(source);
      } else if (source.constructor === Function) {
        var arg = source.toString().match(/\((.*?)\)/)[1];
        var content = source.toString().replace(/\n|\r/g, "").match(/\{(.*)\}/)[1];
        target = new Function(arg, content)
      } else {
        target = new source.constructor();
      }
    }
    var names = Object.getOwnPropertyNames(source).concat(Object.getOwnPropertySymbols(source));
     for (var i = 0; i < names.length; i++) {
       if (names[i] === "constructor") {
        Object.defineProperty(target, "constructor", {
          value: source.constructor
        });
        continue;
      }
      var desc = Object.getOwnPropertyDescriptor(source, names[i]);
       if ((typeof desc.value === "object" && desc.value !== null) || typeof desc.value === "function") {
        var o = cloneObject(desc.value)
        Object.defineProperty(target, names[i], {
          value: o,
          enumerable: desc.enumerable,
          writable: desc.writable,
          configurable: desc.configurable
        })
      } else {
        Object.defineProperty(target, names[i], desc);
      }
    }
    return target;
  }
   1、Object.assign(目标对象,源对象)
   2、
  var obj1={}
   for(var key in obj){
      obj1[key]=obj[key]
  }
   3、obj1={...obj};

9、url 的组成 ?

http:/https:   协议
www.baidu.com 域名
:8080 端口
/sf/vsearch 路径
?wd=百度热搜   查询(可有可无)
#a=1&b=2 哈希值(可有可无)                        

10、常见的跨域方式 ?

11、Promise 的使用场景 ?

12、let, const, var 的区别 ?

声明方式变量提升暂时性死区重复声明初始值作用域
var允许不存在允许不需要非块级
let不允许存在不允许不需要块级
const不允许存在不允许需要块级

13、对 this 的理解, 三种改变 this 的方式 ?

14、cookie, localStorage,sessionStorage 的区别 ?

存储方式 作用与特性 存储数量及大小

存储方式
存储用户信息,获取数据需要与服务器建立连接。
以路径存储,上层路径不能访问下层的路径cookie,下层的路径cookie可以访问上层的路径cookie
作用与特性

可存储的数据有限,且依赖于服务器,无需请求服务器的数据尽量不要存放在cookie 中,以免影响页面性能。

可设置过期时间。

存储数量及大小 将cookie控制在4095B以内,超出的数据会被忽略。
IE6或更低版本 最多存20个cookie;
IE7及以上
版本 多可以有50个;
Firefox多 50个;
chrome和Safari没有做硬性限制。

cookie最大特征就是可以在页面与服务器间互相传递,当发送或者接受数据时自动传递
localStorage
存储客户端信息,无需请求服务器。

数据永久保存,除非用户手动清理客户端缓存。

开发者可自行封装一个方法,设置失效时间。5M左右,各浏览器的存储空间有差异。

任何地方都可以存都可以取

操作简单
sessionStorage

存储客户端信息,无需请求服务器。

数据保存在当前会话,刷新页面数据不会被清除,结束会话(关闭浏览器、关闭页面、跳转页面)数据失效。

5M左右,各浏览器的存储空间有差异。

同页面不同窗口中数据不会共享

15、输入 url 到打开页面 都做了什么事情 ?

16、原生 ajax 的流程 ?

  创建xhr
  var xhr=new XMLHTTPRequest()
  侦听通信状态改变的事件
  xhr.addEventListener("readystatechange",readyStateChangeHandler);
  Method 分为 get post put delete等等
  Async 异步同步
  name和password是用户名和密码
  xhr.open(Method,URL,Async,name,password)
  发送内容给服务器
  xhr.send(内容)

   function readyStateChangeHandler(e){
    当状态是4时,并且响应头成功200时,
      if(xhr.readyState===4 && xhr.status===200){
        打印返回的消息
        console.log(xhr.response)
      }
  }

17、如何实现继承 ?

function A(x,y){
this.x = x
this.y = y
}
A.prototype.run = function(){}
// 寄生继承 二者一起使用
function B(x,y){
A.call(this,x,y) // 借用继承
}
B.prototype = new A() // 原型继承
// 组合继承
Function.prototype.extends = function(superClass){
 function F(){}
F.prototype = superClass.prototype
 if(superClass.prototype.constructor !== superClass){
  Object.defineProperty(superClass.prototype,'constructor',{value:superClass})
}
let proto = this.prototype
this.prototype = new F()
let names = Reflect.ownKeys(proto)
 for(let i = 0; i < names.length;i++){
  let desc = Object.getOwnPropertyDescriptor(proto,names[i])
  Object.defineProperty(this.prototypr,name[i],desc)
}
this.prototype.super = function(arg){
  superClass.apply(this,arg)
}
this.prototype.supers = superClass.prototype
}

18、null 和 undefined 的区别 ?

19、函数的节流和防抖 ?

节流是指当一个事件触发的时候,为防止事件的连续频繁触发,设置定时器,达到一种一段事件内只触发一次的效果,在当前事件内不会再次触发,当前事件结束以后,再次触发才有效.
function thro(cb,wait){
let timeOut
return function(){
   if(timeOut) return
  timeOut = setTimeout(function(){
    cb()
    clearTimeout(timeOut)
    timeOut = null
  },wait)
}
}
防抖是指当一个事件触发的时候, 为防止频繁触发事件, 设置定时器,以达到一种 频繁触发期间不处理, 只有当最后一次连续触发结束以后才处理
function debounce(cb,wait){
let timer
return function(){
  clearTimeout(timer)
  timer = setTimeout(()=>cb(),wait)
}
}

20、什么是 Promise ?

Promise 是异步编程的一种解决方案:从语法上讲,promise是一个对象,从它可以获取异步操作的消息;
 
从本意上讲,它是承诺,承诺它过一段时间会给你一个结果。
 
promise有三种状态:pending(等待态),fulfiled(成功态),rejected(失败态);状态一旦改变,就不会再变。创造promise实例后,它会立即执行

promise是用来解决两个问题的:

回调地狱,代码难以维护, 常常第一个的函数的输出是第二个函数的输入这种现象

promise可以支持多个并发的请求,获取并发请求中的数据

这个promise可以解决异步的问题,本身不能说promise是异步的

21、普通函数与箭头函数的区别 ?

普通函数和箭头函数的区别:

22、设计模式有哪些, 分别说一说 ?

共23种设计模式,介绍其中6种应用较为广泛的模式。

23、Promsie 和 async/await 的区别和使用 ?

区别:

24、谈一谈垃圾回收机制 ?

垃圾回收是动态存储管理技术,会自动地释放“垃圾‘’(不再被程序引用的对象),按照特定的垃圾收集算法来实现资源自动回收的功能。回收的两种机制

25、数组去重 ?

for(var i=0;i<arr.length;i++){
for(var j=i+1;j<arr.length;){
if(arr[i]===arr[j]) arr.splice(j,1);
else j++; // 核心
}
}
var arr1=[];
xt: for(var i=0;i<arr.length;i++){
for(var j=0;j<arr1.length;j++){
if(arr1[j]===arr[i]) continue xt;
}
arr1.push(arr[i]);
}
var arr1=[];
for(var i=0;i<arr.length;i++){
if(arr1.indexOf(arr[i])<0) arr1.push(arr[i])
}
var arr1=[];
for(var i=0;i<arr.length;i++){
if(!(~arr1.indexOf(arr[i]))) arr1.push(arr[i])
}
var arr1=[];
for(var i=0;i<arr.length;i++){
if(!arr1.includes(arr[i])) arr1.push(arr[i])
}
arr=[1,2,3,1,2,3,1,2,3]
new Set(arr);

26、判断对象为空 ?

使用JSON.stringify()将对象转换为json字符串;
JSON.stringify(obj) === '{}'
使用for...in循环遍历对象除Symbol以外的所有可枚举属性,当对象有属性存在返回false, 否则返回
true。
const obj = {}
function isObjectEmpty(obj){
for(var key in obj){
return false
}
return true
}
console.log(isObjectEmpty(obj))
Object.getOwnPropertyNames() 方法会返回该对象所有可枚举和不可枚举属性的属性名(不含Symbol
属性)组成的数组。然后再通过判断返回的数组长度是否为零,如果为零的话就是空对象。
Object.getOwnPropertyNames(obj).length === 0
Object.keys() 是 ES5 新增的一个对象方法,该方法返回一个数组,包含指定对象自有的可枚举属性(不
含继承的和Symbol属性)。用此方法只需要判断返回的数组长度是否为零,如果为零的话就是空对象。

27、如何用一次循环找到数组中两个最大的值 ?

var arr=[1,4,10,11,11,2,5,7,2,3,4];
var [max,second]=arr[0]>arr[1] ? [arr[0],arr[1]] : [arr[1],arr[0]];
 for(var i=2;i<arr.length;i++){
   if(arr[i]>max){
     second=max;
     max=arr[i];
  }else if(arr[i]<=max && arr[i]>second){
     second=arr[i];
  }
}

28、new 一个对象的过程 ?

29、箭头函数为什么不能用 new ?

因为箭头函数没有prototype也没有自己的this指向并且不可以使用arguments。

30、如何实现数组的复制 ?

var arr1=[];
 for(var i=0;i<arr.length;i++){
   if(i in arr) arr1[i]=arr[i]
}
  var arr1=[...arr];
var arr1=arr.slice();
var arr1=arr.concat();
var arr1=arr.map(item=>item);
var arr1=arr.reduce((v,t)=>v.push(t),[])

– End –

   
分类:前端工程师 作者:开发喵 发表于:2023-07-28 21:53:59 阅读量:91
<<   >>


powered by kaifamiao