2018面试总结第一轮

头条面试题卷一


 

JS里的New干了什么

  let obj = new Base();  

 

这样代码的结果是什么,我们在Javascript引擎中看到的对象模型是:
\

new操作符具体干了什么呢?其实很简单,就干了三件事情。

let obj  = {}; 
obj.__proto__ = Base.prototype;
Base.call(obj);

第一行,我们创建了一个空对象obj
第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象
第三行,我们将Base函数对象的this指针替换成obj,然后再调用Base函数,于是我们就给obj对象赋值了一个id成员变量,这个成员变量的值是”base”。 


如果我们给Base.prototype的对象添加一些函数会有什么效果呢?
例如代码如下:

  Base.prototype.toString = function() {     
    return this.id;
}

那么当我们使用new创建一个新对象的时候,根据__proto__的特性,toString这个方法也可以做新对象的方法被访问到。于是我们看到了:
构造子中,我们来设置‘类’的成员变量(例如:例子中的id),构造子对象prototype中我们来设置‘类’的公共方法。于是通过函数对象和Javascript特有的__proto__与prototype成员及new操作符,模拟出类和类实例化的效果。

 

Position定位属性

static默认定位

relative相对定位

absolute绝对定位

fixed固定定位

sticky粘性定位

 

HTML中meta标签的作用

<meta> 元素可提供有关某个 HTML 元素的元信息 (meta-information),比如描述、针对搜索引擎的关键词以及刷新频率。

参考链接

<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="format-detection"content="telephone=no, email=no" />
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no" />
<meta name="apple-mobile-web-app-capable" content="yes" /><!-- 删除苹果默认的工具栏和菜单栏 -->
<meta name="apple-mobile-web-app-status-bar-style" content="black" /><!-- 设置苹果工具栏颜色 -->
<meta name="format-detection" content="telphone=no, email=no" /><!-- 忽略页面中的数字识别为电话,忽略email识别 -->
<!-- 启用360浏览器的极速模式(webkit) -->
<meta name="renderer" content="webkit">
<!-- 避免IE使用兼容模式 -->
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<!-- 针对手持设备优化,主要是针对一些老的不识别viewport的浏览器,比如黑莓 -->
<meta name="HandheldFriendly" content="true">
<!-- 微软的老式浏览器 -->
<meta name="MobileOptimized" content="320">
<!-- uc强制竖屏 -->
<meta name="screen-orientation" content="portrait">
<!-- QQ强制竖屏 -->
<meta name="x5-orientation" content="portrait">
<!-- UC强制全屏 -->
<meta name="full-screen" content="yes">
<!-- QQ强制全屏 -->
<meta name="x5-fullscreen" content="true">
<!-- UC应用模式 -->
<meta name="browsermode" content="application">
<!-- QQ应用模式 -->
<meta name="x5-page-mode" content="app">
<!-- windows phone 点击无高光 -->
<meta name="msapplication-tap-highlight" content="no">
<!-- 适应移动端end -->

 

web中实现长连接的方式

ajax 参考链接

websocket 参考链接

iframe

 

DOM的删除,移除,复制,插入,查询方法

//查找节点
document.getElementById("id");//通过id查找,返回唯一的节点,如果有多个将会返回第一个,在IE6、7中有个bug,会返回name值相同的元素,所有要做一个兼容
document.getElementsByClassName("class");//通过class查找,返回节点数组
document.getElementsByTagName("div");
document.querySelector(); //方法返回文档中匹配指定 CSS 选择器的一个元素
document.querySelectorAll();
//创建节点
document.createDocumentFragment();//创建内存文档碎片
document.createElement();//创建元素
document.createTextNode();//创建文本节点
 
//添加节点
var ele = document.getElementById("my_div");
var oldEle = document.createElement("p");
var newEle=document.createElement("div");
ele.appendChild(oldEle);
//移除
ele.removeChild(oldEle);
//替换
ele.replaceChild(newEle,oldEle);
//插入
ele.insertBefore(oldEle,newEle);//在newEle之前插入 oldEle节点
 
//复制节点
var cEle = oldEle.cloneNode(true);//深度复制,复制节点下面所有的子节点
cEle = oldEle.cloneNode(false);//只复制当前节点,不复制子节点
 
//移动节点
var cloneEle = oldEle.cloneNode(true);//被移动的节点
document.removeChild(oldEle);//删除原节点

 参考链接

 

浏览器缓存机制有哪几种

正解答案

http缓存详解参考链接

 

exports 和 module.exports 的区别

正解答案

“原理很简单,即 module.exports 指向新的对象时,exports 断开了与 module.exports 的引用,那么通过 exports = module.exports 让 exports 重新指向 module.exports 即可。” 这一段有点画蛇添足。引用官网的一句 “如果一个新的值被赋值给 exports,它就不再绑定到 module.exports”。

当你搞不明白export和module.export的关系的时候,就一直使用module.export好了。export是module.export的引用,然后export是个局部变量,module是个全局变量。

 

原生实现Jsonp

科普文章

解决方法

 1 function ajax(params) {   
 2 
 3   params = params || {};   
 4 
 5   params.data = params.data || {};   
 6 
 7   var json = params.jsonp ? jsonp(params) : json(params);      
 8 
 9 
10 
11   // jsonp请求   
12 
13   function jsonp(params) {   
14 
15     //创建script标签并加入到页面中   
16 
17     var callbackName = params.jsonp;   
18 
19     var head = document.getElementsByTagName('head')[0];   
20 
21     // 设置传递给后台的回调参数名   
22 
23     params.data['callback'] = callbackName;   
24 
25     var data = formatParams(params.data);   
26 
27     var script = document.createElement('script');   
28 
29     head.appendChild(script);    
30 
31  
32 
33     //创建jsonp回调函数   
34 
35     window[callbackName] = function(json) {   
36 
37       head.removeChild(script);   
38 
39       clearTimeout(script.timer);   
40 
41       window[callbackName] = null;   
42 
43       params.success && params.success(json);   
44 
45     };    
46 
47 
48 
49     //发送请求   
50 
51     script.src = params.url + '?' + data;    
52 
53 
54 
55     //为了得知此次请求是否成功,设置超时处理   
56 
57     if(params.time) {   
58 
59      script.timer = setTimeout(function() {   
60 
61        window[callbackName] = null;   
62 
63        head.removeChild(script);   
64 
65        params.error && params.error({   
66 
67          message: '超时'   
68 
69        });   
70 
71      }, time);   
72 
73     }   
74 
75   };
<script type="text/javascript">
    //定义一个发送Jsonp请求的函数
    function jsonp(obj) {
        //定义一个处理Jsonp返回数据的回调函数
        window["callback"] = function(object) {
            obj.success(JSON.parse(object));
        }
        var script = document.createElement("script");
        //组合请求URL
        script.src = obj.url + "?fn=callback";
        for(key in obj.data){
            script.src +="&" + key + "=" + obj.data[key];
        }
        //将创建的新节点添加到BOM树上
        document.getElementsByTagName("body")[0].appendChild(script);  
    }
</script>
 
<script type="text/javascript">
    //调用Jsonp函数发送jsonp请求
    jsonp({
        url:"http://localhost/index.php",
        data:{
            name:"小明",
        },
        success:function(obj) {
            alert("性别" + obj.sex);
        }
    });
</script>

 

Html5新增input类型

  • email
  • url
  • number
  • range
  • Date pickers (date, month, week, time, datetime, datetime-local)
  • search
  • color

 

BFC是什么,怎么生成

  BFC 定义

  BFC(Block formatting context)直译为"块级格式化上下文"。它是一个独立的渲染区域,只有Block-level box参与, 它规定了内部的Block-level Box如何布局,并且与这个区域外部毫不相干。

  BFC布局规则:

  1. 内部的Box会在垂直方向,一个接一个地放置。
  2. Box垂直方向的距离由margin决定。属于同一个BFC的两个相邻Box的margin会发生重叠
  3. 每个元素的margin box的左边, 与包含块border box的左边相接触(对于从左往右的格式化,否则相反)。即使存在浮动也是如此。
  4. BFC的区域不会与float box重叠。
  5. BFC就是页面上的一个隔离的独立容器,容器里面的子元素不会影响到外面的元素。反之也如此。
  6. 计算BFC的高度时,浮动元素也参与计算

参考链接

 

JS继承

参考链接

 

Vue原理

文字参考链接

 

双向绑定

 1 <body>
 2     <div id="app">
 3         <input type="text" id="txt">
 4         <p id="show-txt"></p>
 5     </div>
 6     <script>
 7         var obj = {}
 8         Object.defineProperty(obj, 'txt', {
 9             get: function () {
10                 return obj
11             },
12             set: function (newValue) {
13                 document.getElementById('txt').value = newValue
14                 document.getElementById('show-txt').innerHTML = newValue
15             }
16         })
17         document.addEventListener('keyup', function (e) {
18             obj.txt = e.target.value
19         })
20     </script>
21 </body>

Object.defineProperty()

方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。如果不指定configurable, writable, enumerable ,则这些属性默认值为false,如果不指定value, get, set,则这些属性默认值为undefined

 1 语法: Object.defineProperty(obj, prop, descriptor)
 2 obj: 需要被操作的目标对象
 3 prop: 目标对象需要定义或修改的属性的名称
 4 descriptor: 将被定义或修改的属性的描述符
 5 
 6 var obj = new Object();
 7 
 8 Object.defineProperty(obj, 'name', {
 9     configurable: false,
10     writable: true,
11     enumerable: true,
12     value: '张三'
13 })
14 
15 console.log(obj.name)  //张三

学习链接

 

头条面试题卷二


 

new webSocket背后的原理。长链接方案。长轮询原理。
 
节流函数。
 
实现原生es6 bind函数。
 1 if (!Function.prototype.binds) {
 2   Function.prototype.binds = function (ctx) {
 3     if (typeof this !== 'function') {
 4       throw new TypeError("NOT_A_FUNCTION -- this is not callable")
 5     }
 6     var _this = this
 7     var slice = Array.prototype.slice
 8     var formerArgs = slice.call(arguments, 1)
 9     // 定义一个中间函数,用于作为继承的中间值
10     var fun = function () {}
11     var fBound = function (){
12       let laterArgs = slice.call(arguments, 0)
13       return _this.apply(ctx, formerArgs.concat(laterArgs))
14     }
15     // 先让 fun 的原型方法指向 _this 即原函数的原型方法,继承 _this 的属性
16     fun.prototype = _this.prototype
17     // 再将 fBound 即要返回的新函数的原型方法指向 fun 的实例化对象
18     // 这样,既能让 fBound 继承 _this 的属性,在修改其原型链时,又不会影响到 _this 的原型链
19     fBound.prototype = new fun()
20     return fBound
21   }
22 }
 
cookie是否有跨域问题,cookie从http迁移到https域名。
cookie存在跨域问题。
 
一个url的访问历程。ip如何映射到物理机。如何配置服务器代理映射。网关相关知识。
 
es7的proxy拦截代理和defineProperty的区别。
 
迭代器函数的原理。
 
继承的方式。
 
对restAPI的理解。get,post,put的区别
 
vue和react的区别,实现双向绑定,两次改变数据哪一次生效。
 
new Promise两次回调会生效几次。
 
如何判断是否是数组。
 
函数式编程和面向对象编程。
 
两个算法题。
 
补充

 1px边框解决方案

 1 .div::after {
 2     content: '';
 3     width: 200%;
 4     height: 200%;
 5     position: absolute;
 6     top: 0;
 7     left: 0;
 8     border: 1px solid #bfbfbf;
 9     border-radius: 4px;
10     -webkit-transform: scale(0.5,0.5);
11     transform: scale(0.5,0.5);
12     -webkit-transform-origin: top left;
13 }

 flex知识

事件冒泡和事件捕获的机制和顺序

Map数据结构

它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。也就是说,Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

map()方法

map()是数组的一个方法,它创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。map()里面的处理函数接受三个参数,分别指代当前元素、当前元素的索引、数组本身。

 1 /**** 原生map() ****/
 2 var arrTmp = [1,2,3];
 3 var arrDouble = arrTmp.map(function(num){
 4     return num*2;
 5 })
 6 // arrDouble -> [2,4,6]
 7  
 8 //注意,使用map()时实际传递了3个参数:
 9 arr.map(function(currentValue, index, array){
10   // currentValue -> 数组中正在处理的当前元素
11   // index -> 数组中正在处理的当前元素的索引
12   // array -> 指向map方法被调用的数组
13 })
14  
15 ["1", "2", "3.5"].map(parseInt); // 结果不是[1, 2, 3],而是[1, NaN, NaN]
16 ["1", "2", "3.5"].map(function(num){ return parseInt(num)}); //得到正确结果[1, 2, 3]
17  
18 //使用map()重组数组
19 var kvArray = [{key: 1, value: 10}, {key: 2, value: 20}, {key: 3, value: 30}];
20 var reformattedArray = kvArray.map(function(obj) { var rObj = {}; rObj[obj.key] = obj.value; return rObj; });
21 // kvArray不变,reformattedArray -> [{1: 10}, {2: 20}, {3: 30}],

 

 

扩展运算符

自定义事件(MDN)

张鑫旭博客

你了解前端路由吗?

 1 class Routers {
 2   constructor() {
 3     this.routes = {};
 4     this.currentUrl = '';
 5     this.refresh = this.refresh.bind(this);
 6     window.addEventListener('load', this.refresh, false);
 7     window.addEventListener('hashchange', this.refresh, false);
 8   }
 9 
10   route(path, callback) {
11     this.routes[path] = callback || function() {};
12   }
13 
14   refresh() {
15     this.currentUrl = location.hash.slice(1) || '/';
16     this.routes[this.currentUrl]();
17   }
18 }
19 
20 window.Router = new Routers();
21 var content = document.querySelector('body');
22 // change Page anything
23 function changeBgColor(color) {
24   content.style.backgroundColor = color;
25 }
26 Router.route('/', function() {
27   changeBgColor('yellow');
28 });
29 Router.route('/blue', function() {
30   changeBgColor('blue');
31 });
32 Router.route('/green', function() {
33   changeBgColor('green');
34 });

 

 1 class Routers {
 2   constructor() {
 3     this.routes = {};
 4     // 在初始化时监听popstate事件
 5     this._bindPopState();
 6   }
 7   // 初始化路由
 8   init(path) {
 9     history.replaceState({path: path}, null, path);
10     this.routes[path] && this.routes[path]();
11   }
12   // 将路径和对应回调函数加入hashMap储存
13   route(path, callback) {
14     this.routes[path] = callback || function() {};
15   }
16 
17   // 触发路由对应回调
18   go(path) {
19     history.pushState({path: path}, null, path);
20     this.routes[path] && this.routes[path]();
21   }
22   // 监听popstate事件
23   _bindPopState() {
24     window.addEventListener('popstate', e => {
25       const path = e.state && e.state.path;
26       this.routes[path] && this.routes[path]();
27     });
28   }
29 }

 

请你实现一个深克隆

阮一峰版的快速排序完全是错的

XSS 中文名为跨站脚本, 是发生在目标用户的浏览器层面上的,当渲染DOM树的过程成发生了不在预期内执行的JS代码时,就发生了XSS攻击。

 
 
 
vue相关

既然React/Vue可以用Event Bus进行组件通信,你可以实现下吗?

class EventEmeitter {
  constructor() {
    this._events = this._events || new Map(); // 储存事件/回调键值对
    this._maxListeners = this._maxListeners || 10; // 设立监听上限
  }
}
// 触发名为type的事件
EventEmeitter.prototype.emit = function(type, ...args) {
  let handler;
  // 从储存事件键值对的this._events中获取对应事件回调函数
  handler = this._events.get(type);
  if (args.length > 0) {
    handler.apply(this, args);
  } else {
    handler.call(this);
  }
  return true;
};

// 监听名为type的事件
EventEmeitter.prototype.addListener = function(type, fn) {
  // 将type事件以及对应的fn函数放入this._events中储存
  if (!this._events.get(type)) {
    this._events.set(type, fn);
  }
};

 

posted @ 2018-07-22 10:37  Paxster  阅读(145)  评论(0编辑  收藏  举报