前端面试题整理JavaScript部分

1.怎样添加、移除、移动、复制、创建和查找节点?

1.1 创建新节点

document.createDocumentFragment() //创建一个DOM片段
document.createElement() //创建一个具体的元素
document.createTextNode() //创建一个文本节点

1.2 添加、移除、替换、插入

document.body.appendChild() //添加
document.body.removeChild() //移除
document.body.replaceChild() //替换
document.body.insertBefore() //插入

1.3 查找

document.getElementsByTagName() //通过标签名称
document.getElementsByName() //通过元素的Name属性的值
document.getElementById() //通过元素Id,唯一性

2.实现一个函数clone,

可以对JavaScript中的5种主要的数据类型(包括Number、String、Object、Array、Boolean)进行值复制。

  • 对象克隆
  • 支持基本数据类型及对象
  • 递归方法

2.1方法一

function clone(obj) {
  var o;
  switch (typeof obj) {
    case "undefined":
      break;
    case "string":
      o = obj + "";
      break;
    case "number":
      o = obj - 0;
      break;
    case "boolean":
      o = obj;
      break;
    case "object": // object 分为两种情况 对象(Object)或数组(Array)
      if (obj === null) {
        o = null;
      } else {
        if (Object.prototype.toString.call(obj).slice(8, -1) === "Array") {
          o = [];
          for (var i = 0; i < obj.length; i++) {
            o.push(clone(obj[i]));
          }
        } else {
          o = {};
          for (var k in obj) {
            o[k] = clone(obj[k]);
          }
        }
      }
      break;
    default:
      o = obj;
      break;
  }
  return o;
}

2.2 方法二:解决父子循环引用问题(深拷贝)

function deepCopy2(obj, parent = null) {
    //创建一个新对象
    let result = {};
    let keys = Object.keys(obj),
        key = null,
        temp = null,
        _parent = parent;
    //该字段有父级则需要追溯该字段的父级
    while (_parent) {
        //如果该字段引用了它的父级,则为循环引用
        if (_parent.originParent === obj) {
            //循环引用返回同级的新对象
            return _parent.currentParent;
        }
        _parent = _parent.parent
    }
    for (let i = 0, len = keys.length; i < len; i++) {
        key = keys[i]
        temp = obj[key]
        // 如果字段的值也是一个新对象
        if (temp && typeof temp === 'object') {
            result[key] = deepCopy2(temp, {
                //递归执行深拷贝,将同级的待拷贝对象与新对象传递给parent,方便追溯循环引用
                originParent: obj,
                currentParent: result,
                parent: parent
            });
        } else {
            result[key] = temp;
        }
    }
    return result;
}

const obj1 = {
    x: 1
}
obj1.z = obj1;

const obj2 = deepCopy2(obj1);

2.3 方法三:深拷贝 解决兄弟循环引用问题

function deepCopy3(obj) {
  // hash表,记录所有的对象的引用关系
  let map = new WeakMap();

  function dp(obj) {
    let result = null;
    let keys = Object.keys(obj);
    let key = null,
      temp = null,
      existobj = null;

    existobj = map.get(obj);
    //如果这个对象已经被记录则直接返回
    if (existobj) {
      return existobj;
    }

    result = {}
    map.set(obj, result);

    for (let i = 0, len = keys.length; i < len; i++) {
      key = keys[i];
      temp = obj[key];
      if (temp && typeof temp === 'object') {
        result[key] = dp(temp);
      } else {
        result[key] = temp;
      }
    }
    return result;
  }
  return dp(obj);
}

const obj = {
  a: {
    name: 'a'
  },
  b: {
    name: 'b'
  },
  c: {

  }
};
c.d.e = obj.a;

const copy = deepCopy3(obj);

3 数组去重

3.1 方法一:

var arr1 =[1,2,2,2,3,3,3,4,5,6],
    arr2 = [];
for(var i = 0,len = arr1.length; i< len; i++){
  if(arr2.indexOf(arr1[i]) < 0){
    arr2.push(arr1[i]);
  }
}
document.write(arr2); // 1,2,3,4,5,6

3.2 方法二

去除数组的重复成员 使用es6的set数据结构

[...new Set(array)]

4、在Javascript中什么是伪数组?如何将伪数组转化为标准数组?

伪数组(类数组):无法直接调用数组方法或期望length属性有什么特殊的行为,但仍可以对真正数组遍历方法来遍历它们。典型的是函数的argument参数,还有像调用getElementsByTagName,document.childNodes之类的,它们都返回NodeList对象都属于伪数组。可以使用Array.prototype.slice.call(fakeArray)将数组转化为真正的Array对象。

function log(){
      var args = Array.prototype.slice.call(arguments);  
//为了使用unshift数组方法,将argument转化为真正的数组
      args.unshift('(app)');
 
      console.log.apply(console, args);
};

5.Javascript中callee和caller的作用?

  • caller是返回一个对函数的引用,该函数调用了当前函数;
  • callee是返回正在被执行的function函数,也就是所指定的function对象的正文。

6.请描述一下cookies,sessionStorage和localStorage的区别

sessionStorage用于本地存储一个会话(session)中的数据,这些数据只有在同一个会话中的页面才能访问并且当会话结束后数据也随之销毁。因此sessionStorage不是一种持久化的本地存储,仅仅是会话级别的存储。而localStorage用于持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。

7.web storage和cookie的区别

Web Storage的概念和cookie相似,区别是它是为了更大容量存储设计的。Cookie的大小是受限的,并且每次你请求一个新的页面的时候Cookie都会被发送过去,这样无形中浪费了带宽,另外cookie还需要指定作用域,不可以跨域调用。
除此之外,Web Storage拥有setItem,getItem,removeItem,clear等方法,不像cookie需要前端开发者自己封装setCookie,getCookie。但是Cookie也是不可以或缺的:Cookie的作用是与服务器进行交互,作为HTTP规范的一部分而存在 ,而Web Storage仅仅是为了在本地“存储”数据而生。

8.统计字符串中字母个数或统计最多字母数。

var str = "aaaabbbccccddfgh";
var obj = {};
for (var i = 0; i < str.length; i++) {
    var v = str.charAt(i);
    if (obj[v] && obj[v].value == v) {
        obj[v].count = ++obj[v].count;
    } else {
        obj[v] = {};
        obj[v].count = 1;
        obj[v].value = v;
    }
}
for (key in obj) {
    document.write(obj[key].value + '=' + obj[key].count + '&nbsp;'); 
    // a=4  b=3  c=4  d=2  f=1  g=1  h=1 
}
posted @ 2020-07-08 12:07  lilycao  阅读(100)  评论(0)    收藏  举报