不知道啥时候记录的面试题了

2018-11-09 15:50 我说呢
fe.jpg

转: 2018 大厂高级前端面试题汇总

2018-11-07 19:12 奔跑的搬砖工
大厂.png

转载内容如下:

本人于7-8月开始准备面试,过五关斩六将,最终抱得网易归,深深感受到高级前端面试的套路。以下是自己整理的面试题汇总,不敢藏私,统统贡献出来。

面试的公司分别是:阿里、网易、滴滴、今日头条、有赞、挖财、沪江、饿了么、携程、喜马拉雅、兑吧、微医、寺库、宝宝树、海康威视、蘑菇街、酷家乐、百分点和海风教育。

以下是面试题汇总,后续阶段会持续深入更新面试题解,共勉!

阿里

使用过的koa2中间件

koa-body原理

介绍自己写过的中间件

有没有涉及到Cluster

介绍pm2

master挂了的话pm2怎么处理

如何和MySQL进行通信

React声明周期及自己的理解

如何配置React-Router

路由的动态加载模块

服务端渲染SSR

介绍路由的history

介绍Redux数据流的流程

Redux如何实现多个组件之间的通信,多个组件使用相同状态如何进行管理

多个组件之间如何拆分各自的state,每块小的组件有自己的状态,它们之间还有一些公共的状态需要维护,如何思考这块

使用过的Redux中间件

如何解决跨域的问题

常见Http请求头

移动端适配1px的问题

介绍flex布局

其他css方式设置垂直居中

居中为什么要使用transform(为什么不使用marginLeft/Top)

使用过webpack里面哪些plugin和loader

webpack里面的插件是怎么实现的

dev-server是怎么跑起来

项目优化

抽取公共文件是怎么配置的

项目中如何处理安全问题

怎么实现this对象的深拷贝

网易

介绍redux,主要解决什么问题

文件上传如何做断点续传

表单可以跨域吗

promise、async有什么区别

搜索请求如何处理(防抖)

搜索请求中文如何请求

介绍观察者模式

介绍中介者模式

观察者和订阅-发布的区别,各自用在哪里

介绍react优化

介绍http2.0

通过什么做到并发请求

http1.1时如何复用tcp连接

介绍service worker

介绍css3中position:sticky

redux请求中间件如何处理并发

介绍Promise,异常捕获

介绍position属性包括CSS3新增

浏览器事件流向

介绍事件代理以及优缺点

React组件中怎么做事件代理

React组件事件代理的原理

介绍this各种情况

前端怎么控制管理路由

使用路由时出现问题如何解决

React怎么做数据的检查和变化

滴滴

react-router怎么实现路由切换

react-router里的 Link标签和 a 标签有什么区别

a 标签默认事件禁掉之后做了什么才实现了跳转

React层面的性能优化

整个前端性能提升大致分几类

import { Button } from 'antd',打包的时候只打包button,分模块加载,是怎么做到的

使用import时,webpack对node_modules里的依赖会做什么

JS异步解决方案的发展历程以及优缺点

Http报文的请求会有几个部分

cookie放哪里,cookie能做的事情和存在的价值

cookie和token都存放在header里面,为什么只劫持前者

cookie和session有哪些方面的区别

React中Dom结构发生变化后内部经历了哪些变化

React挂载的时候有3个组件,textComponent、composeComponent、domComponent,区别和关系,Dom结构发生变化时怎么区分data的变化,怎么更新,更新怎么调度,如果更新的时候还有其他任务存在怎么处理

key主要是解决哪一类的问题,为什么不建议用索引index(重绘)

Redux中异步的请求怎么处理

Redux中间件是什么东西,接受几个参数(两端的柯里化函数)

柯里化函数两端的参数具体是什么东西

中间件是怎么拿到store和action,然后怎么处理

state是怎么注入到组件的,从reducer到组件经历了什么样的过程

koa中response.send、response.rounded、response.json发生了什么事,浏览器为什么能识别到它是一个json结构或是html

koa-bodyparser怎么来解析request

webpack整个生命周期,loader和plugin有什么区别

介绍AST(Abstract Syntax Tree)抽象语法树

安卓Activity之间数据是怎么传递的

安卓4.0到6.0过程中WebView对js兼容性的变化

WebView和原生是如何通信

跨域怎么解决,有没有使用过Apache等方案

今日头条

对async、await的理解,内部原理

介绍下Promise,内部实现

清除浮动

定位问题(绝对定位、相对定位等)

从输入URL到页面加载全过程

tcp3次握手

tcp属于哪一层(1 物理层 -> 2 数据链路层 -> 3 网络层(ip)-> 4 传输层(tcp) -> 5 应用层(http))

redux的设计思想

接入redux的过程

绑定connect的过程

connect原理

webpack介绍

== 和 ===的区别,什么情况下用相等==

bind、call、apply的区别

动画的了解

介绍下原型链(解决的是继承问题吗)

对跨域的了解

有赞

Linux 754 介绍

介绍冒泡排序,选择排序,冒泡排序如何优化

transform动画和直接使用left、top改变位置有什么优缺点

如何判断链表是否有环

介绍二叉搜索树的特点

介绍暂时性死区

ES6中的map和原生的对象有什么区别

观察者和发布-订阅的区别

react异步渲染的概念,介绍Time Slicing 和 Suspense

16.X声明周期的改变

16.X中props改变后在哪个生命周期中处理

介绍纯函数

前端性能优化

pureComponent和FunctionComponent区别

介绍JSX

如何做RN在安卓和IOS端的适配

RN为什么能在原生中绘制成原生组件(bundle.js)

介绍虚拟DOM

如何设计一个localStorage,保证数据的实效性

如何设计Promise.all()

介绍高阶组件

sum(2, 3)实现sum(2)(3)的效果

react性能优化

两个对象如何比较

挖财

JS的原型

变量作用域链

call、apply、bind的区别

防抖和节流的区别

介绍各种异步方案

react生命周期

介绍Fiber

前端性能优化

介绍DOM树对比

react中的key的作用

如何设计状态树

介绍css,xsrf

http缓存控制

项目中如何应用数据结构

native提供了什么能力给RN

如何做工程上的优化

shouldComponentUpdate是为了解决什么问题

如何解决props层级过深的问题

前端怎么做单元测试

webpack生命周期

webpack打包的整个过程

常用的plugins

pm2怎么做进程管理,进程挂掉怎么处理

不用pm2怎么做进程管理

沪江

介绍下浏览器跨域

怎么去解决跨域问题

jsonp方案需要服务端怎么配合

Ajax发生跨域要设置什么(前端)

加上CORS之后从发起到请求正式成功的过程

xsrf跨域攻击的安全性问题怎么防范

使用Async会注意哪些东西

Async里面有多个await请求,可以怎么优化(请求是否有依赖)

Promise和Async处理失败的时候有什么区别

Redux在状态管理方面解决了React本身不能解决的问题

Redux有没有做过封装

react生命周期,常用的生命周期

对应的生命周期做什么事

遇到性能问题一般在哪个生命周期里解决

怎么做性能优化(异步加载组件...)

写react有哪些细节可以优化

React的事件机制(绑定一个事件到一个组件上)

介绍下事件代理,主要解决什么问题

前端开发中用到哪些设计模式

React/Redux中哪些功能用到了哪些设计模式

JS变量类型分为几种,区别是什么

JS里垃圾回收机制是什么,常用的是哪种,怎么处理的

一般怎么组织CSS(Webpack)

饿了么

小程序里面开页面最多多少

React子父组件之间如何传值

Emit事件怎么发,需要引入什么

介绍下React高阶组件,和普通组件有什么区别

一个对象数组,每个子对象包含一个id和name,React如何渲染出全部的name

在哪个生命周期里写

其中有几个name不存在,通过异步接口获取,如何做

渲染的时候key给什么值,可以使用index吗,用id好还是index好

webpack如何配sass,需要配哪些loader

配css需要哪些loader

如何配置把js、css、html单独打包成一个文件

div垂直水平居中(flex、绝对定位)

两个元素块,一左一右,中间相距10像素

上下固定,中间滚动布局如何实现

[1, 2, 3, 4, 5]变成[1, 2, 3, a, b, 5]

取数组的最大值(ES5、ES6)

apply和call的区别

ES5和ES6有什么区别

some、every、find、filter、map、forEach有什么区别

上述数组随机取数,每次返回的值都不一样

如何找0-5的随机数,95-99呢

页面上有1万个button如何绑定事件

如何判断是button

页面上生成一万个button,并且绑定事件,如何做(JS原生操作DOM)

循环绑定时的index是多少,为什么,怎么解决

页面上有一个input,还有一个p标签,改变input后p标签就跟着变化,如何处理

监听input的哪个事件,在什么时候触发

携程

对React看法,有没有遇到一些坑

对闭包的看法,为什么要用闭包

手写数组去重函数

手写数组扁平化函数

介绍下Promise的用途和性质

Promise和Callback有什么区别

React生命周期

两道手写算法题

喜马拉雅

ES6新的特性

介绍Promise

Promise有几个状态

说一下闭包

React的生命周期

componentWillReceiveProps的触发条件是什么

React16.3对生命周期的改变

介绍下React的Filber架构

画Filber渲染树

介绍React高阶组件

父子组件之间如何通信

Redux怎么实现属性传递,介绍下原理

React-Router版本号

网站SEO怎么处理

介绍下HTTP状态码

403、301、302是什么

缓存相关的HTTP请求头

介绍HTTPS

HTTPS怎么建立安全通道

前端性能优化(JS原生和React)

用户体验做过什么优化

对PWA有什么了解

对安全有什么了解

介绍下数字签名的原理

前后端通信使用什么方案

RESTful常用的Method

介绍下跨域

Access-Control-Allow-Origin在服务端哪里配置

csrf跨站攻击怎么解决

前端和后端怎么联调

兑吧

localStorage和cookie有什么区别

CSS选择器有哪些

盒子模型,以及标准情况和IE下的区别

如何实现高度自适应

prototype和——proto——区别

_construct是什么

new是怎么实现的

promise的精髓,以及优缺点

如何实现H5手机端的适配

rem、flex的区别(root em)

em和px的区别

React声明周期

如何去除url中的#号

Redux状态管理器和变量挂载到window中有什么区别

webpack和gulp的优缺点

如何实现异步加载

如何实现分模块打包(多入口)

前端性能优化(1js css;2 图片;3 缓存预加载; 4 SSR; 5 多域名加载;6 负载均衡)

并发请求资源数上限(6个)

base64为什么能提升性能,缺点

介绍webp这个图片文件格式

介绍koa2

Promise如何实现的

异步请求,低版本fetch如何低版本适配

ajax如何处理跨域

CORS如何设置

jsonp为什么不支持post方法

介绍同源策略

React使用过的一些组件

介绍Immuable

介绍下redux整个流程原理

介绍原型链

如何继承

微医

介绍JS数据类型,基本数据类型和引用数据类型的区别

Array是Object类型吗

数据类型分别存在哪里

var a  = {name: '前端开发'}; 
var b = a; 
a = null; // 那么b输出什么

var a = {b: 1} 存放在哪里

var a = {b: {c: 1}}存放在哪里

栈和堆的区别

垃圾回收时栈和堆的区别

数组里面有10万个数据,取第一个元素和第10万个元素的时间相差多少

栈和堆具体怎么存储

介绍闭包以及闭包为什么没清除

闭包的使用场景

JS怎么实现异步

异步整个执行周期

Promise的三种状态

Async/Await怎么实现

Promise和setTimeout执行先后的区别

JS为什么要区分微任务和宏任务

Promise构造函数是同步还是异步执行,then呢

发布-订阅和观察者模式的区别

JS执行过程中分为哪些阶段

词法作用域和this的区别

平常是怎么做继承

深拷贝和浅拷贝

loadsh深拷贝实现原理

ES6中let块作用域是怎么实现的

React中setState后发生了什么

setState为什么默认是异步

setState什么时候是同步的

为什么3大框架出现以后就出现很多native(RN)框架(虚拟DOM)

虚拟DOM主要做了什么

虚拟DOM本身是什么(JS对象)

304是什么

打包时Hash码是怎么生成的

随机值存在一样的情况,如何避免

使用webpack构建时有无做一些自定义操作

webpack做了什么

a,b两个按钮,点击aba,返回顺序可能是baa,如何保证是aba(Promise.then)

node接口转发有无做什么优化

node起服务如何保证稳定性,平缓降级,重启等

RN有没有做热加载

RN遇到的兼容性问题

RN如何实现一个原生的组件

RN混原生和原生混RN有什么不同

什么是单页项目

遇到的复杂业务场景

Promise.all实现原理

寺库

介绍Promise的特性,优缺点

介绍Redux

RN的原理,为什么可以同时在安卓和IOS端运行

RN如何调用原生的一些功能

介绍RN的缺点

介绍排序算法和快排原理

堆和栈的区别

介绍闭包

闭包的核心是什么

网络的五层模型

HTTP和HTTPS的区别

HTTPS的加密过程

介绍SSL和TLS

介绍DNS解析

JS的继承方法

介绍垃圾回收

cookie的引用为了解决什么问题

cookie和localStorage的区别

如何解决跨域问题

前端性能优化

宝宝树

使用canvas绘图时如何组织成通用组件

formData和原生的ajax有什么区别

介绍下表单提交,和formData有什么关系

介绍redux接入流程

rudux和全局管理有什么区别(数据可控、数据响应)

RN和原生通信

介绍MVP怎么组织

介绍异步方案

promise如何实现then处理

koa2中间件原理

常用的中间件

服务端怎么做统一的状态处理

如何对相对路径引用进行优化

node文件查找优先级

npm2和npm3+有什么区别

海康威视

knex连接数据库响应回调

介绍异步方案

如何处理异常捕获

项目如何管理模块

前端性能优化

JS继承方案

如何判断一个变量是不是数组

变量a和b,如何交换

事件委托

多个 li 标签生成的Dom结构是一个类数组

类数组和数组的区别

dom的类数组如何转成数组

介绍单页面应用和多页面应用

redux状态树的管理

介绍localstorage的API

蘑菇街

html语义化的理解

b 标签和 strong 标签的区别

对闭包的理解

工程中闭包使用场景

介绍this和原型

使用原型最大的好处

react设计思路

为什么虚拟DOM比真实DOM性能好

react常见的通信方式

redux整体的工作流程

redux和全局对象之间的区别

Redux数据回溯设计思路

单例、工厂、观察者项目中实际场景

项目中树的使用场景以及了解

工作收获

酷家乐

react生命周期

react性能优化

添加原生事件不移除为什么会内存泄露

还有哪些地方会内存泄露

setInterval需要注意的点

定时器为什么是不精确的

setTimeout(1)和setTimeout(2)之间的区别

介绍宏任务和微任务

promise里面和then里面执行有什么区别

介绍pureComponet

介绍Function Component

React数据流

props和state的区别

介绍react context

介绍class和ES5的类以及区别

介绍箭头函数和普通函数的区别

介绍defineProperty方法,什么时候需要用到

for..in 和 object.keys的区别

介绍闭包,使用场景

使用闭包特权函数的使用场景

get和post有什么区别

百分点

React15/16.x的区别

重新渲染render会做些什么

哪些方法会触发react重新渲染

state和props触发更新的生命周期分别有什么区别

setState是同步还是异步

对无状态组件的理解

介绍Redux工作流程

介绍ES6的功能

let、const以及var的区别

浅拷贝和深拷贝的区别

介绍箭头函数的this

介绍Promise和then

介绍快速排序

算法:前K个最大的元素

海风教育

对react看法,它的优缺点

使用过程中遇到的问题,如何解决的

react的理念是什么(拿函数式编程来做页面渲染)

JS是什么范式语言(面向对象还是函数式编程)

koa原理,为什么要用koa(express和koa对比)

使用的koa中间件

ES6使用的语法

Promise 和 async/await 和 callback的区别

Promise有没有解决异步的问题(promise链是真正强大的地方)

Promise和setTimeout的区别(Event Loop)

进程和线程的区别(一个node实例就是一个进程,node是单线程,通过事件循环来实现异步

介绍下DFS深度优先

介绍下观察者模式

观察者模式里面使用的数据结构(不具备顺序 ,是一个list)

转载自: 前端大全

页面统计时间问题解决过程

2018-10-15 17:38 我说呢

背景交代下:百度地图项目中一个H5的活动页面,需要统计下用户的PV、UV、页面停留时长等数据,以便验收运营效果,调整策略。

其实问题主要在于统计页面的停留时间上;本以为就是一个在开始进入的时候发送一个ajax请求,记录下时间,在退出监听window.onbeforeunload事件发送一下请求就搞定了。

第一版代码实现:

window.onunload = window.onbeforeunload = function (e) {
    $.ajax({...});
}

然而,结果并不那么如意:在PC端成功了,在Mobile上基本上没有统计到结束的时间。发现被浏览器cancel掉了,原来是异步的问题,然后就改成同步的。

var request = new XMLHttpRequest();
request.open('GET', url, false); // 同步请求
request.send(null);
伤心.png

测试下,iPhone可以了,安卓机又不行了(郁闷.png)。经过一番调试发现:

安卓机在百度地图app退出H5页面时,并不会触发onbeforeunload,应该是并不会把当前webview销毁,而是在下次重新进入一个H5页面的时候会销毁上一个(触发上一个H5的onbeforeunload事件)

机智.png

发现根本没有触发ajax,经过一顿google后,发现另一个事件,visibilitychange:

document.addEventListener('visibilitychange', function() {
  console.log( document.visibilityState );
});

但是这个事件的弊端是,如果app只是退出到后台运行(H5页面并没有关闭),也会执行该事件。

ganga.png

所以,带来的就是不管退出到后台还是真正的关闭webview,都会发送ajax,说 我结束了,其实有的时候并没有结束。

还有一点优化的就是,如果用户退出到后台会造成统计时间不准,因为你真正的退出的时候会再次发一次,这时候中间可能有很长时间并没有看当前页面,需要记录下退出到后台的时间,然后去除掉就可以了。

最后的伪代码:

if (navigator.userAgent.toLowerCase().indexOf('android') > 0) {
    document.addEventListener('visibilitychange', function () {
        if (document.visibilityState != 'hidden') {
            ...sync ajax...
        }
    });
}
else {
    window.addEventListener('pagehide', function () {
        ...sync ajax...
    }, false);
}

其中pagehide与onbeforeunload差不多(反正没找到不同)。

另外,中间还用了一个不太好的,就是使用了轮询机制(心跳机制)。弊端是不管关没关闭都会触发,另外统计时间不是那么准确。

参考资料:visibilitychangePageVisibilityAPI

关于elementUI scope 设置th样式

2018-09-27 14:53 我说呢
vueloader

关于这个问题,困扰了有一段时间了,上次写东西就发现了这个问题,当时比较着急就写了全局的样式,后来给忘了(惭愧.gif)。

今天看了下官网,里面专门有对scoped的css的说明vue-loader官网

下面说明下原因:

使用scoped后的style标签会在vue-loader里进行处理。这里所谓的局部样式就是在你当前组件里的所有html标签打一个data-tag。

例如,如果你在vue文件中这样编写css:

<style lang='stylus' scoped>
    .home {
        .el-table th .cell {
            background-color: red;
        }
    }
</style>

编译后的css样式如下:

.home .el-table th .cell[data-v-03b663c3] {
  background-color: red;
}

然后在elementUI中el-table中你的一个子组件,vue-loader在编译中对于子组件只对子组件的根元素打上tag,不会对th以及之下的div.cell打上tag,所以样式寻找中找不到这个,那就注定不生效了。

使用 scoped 后,父组件的样式将不会渗透到子组件中。不过一个子组件的根节点会同时受其父组件的 scoped CSS 和子组件的 scoped CSS 的影响。这样设计是为了让父组件可以从布局的角度出发,调整其子组件根元素的样式 --- 来自vue-loader官网

解决方法

深度作用选择器

如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:

<style scoped>
.a >>> .b { /* ... */ }
</style>

编译后:

.a[data-v-f3f3eg9] .b { /* ... */ }

搞定。。

mac 如何管理多个公钥、私钥

2018-03-27 22:55 奔跑的搬砖工

当有多对公/私钥对时,管理和操作会变复杂。使用 ssh 时需要通过 -i 指定私钥文件,比较麻烦。可以通过在 .ssh 目录下新建一个 config 文件来进行管理。

git.png

1.新增ssh的配置文件,并修改权限(如果有报错就修改权限)。

touch ~/.ssh/config
chmod 600 ~/.ssh/config

2.配置内容如下(还有别名,端口等参数,不多做介绍)

Host *.xxxxxx.xxx  
    IdentityFile ~/.ssh/xxxxxxxx
    User xxxxx  

Host github.com  
    IdentityFile ~/.ssh/id_rsa_for_github  
    User git  

3.搞定

building for production...Killed

2018-03-06 17:35 奔跑的搬砖工

这个已经遇到过两次了,是时候记录下了

在vue项目中运行npm run build的时候报错了

img

原理

按照他人的说法是,服务器内存不够用了,这样就给他配置一个单独的内存出来就解决了

解决方法

 sudo /bin/dd if=/dev/zero of=/var/swap.1 bs=1M count=1024
 sudo /sbin/mkswap /var/swap.1
 sudo /sbin/swapon /var/swap.1

vue-cli webpack css 图片路径

2018-03-05 15:17 我说呢

图片放在了assets文件夹下,img和background-image引用都用相对路径,build的时候设置assetsPublicPath: './',打包出来后发现background-image的路径出现了问题

解决方法 (the first)

1.先在data里面导入这张图片,例如:bg:require(‘./openIndexBG2.jpg’)

2.然后在template里面对需要background-image属性的DOM做个绑定,例如::style=“{backgroundImage: ‘url(‘ +bg + ‘)’}“

这个方法确实是可以解决图片路径的问题,不过有的时候是不能直接写style样式的就不生效了

解决方法 (the second)

在build的utils.js文件中添加一行:

webpack_build_utils

publicPath根据项目目录配置

转: 你所忽略的js隐式转换

2018-02-06 10:44 奔跑的搬砖工

你有没有在面试中遇到特别奇葩的js隐形转换的面试题,第一反应是怎么会是这样呢?难以自信,js到底是怎么去计算得到结果,你是否有深入去了解其原理呢?下面将深入讲解其实现原理。

其实这篇文章初稿三个月前就写好了,在我读一些源码库时,遇到了这些基础知识,想归档整理下,就有了这篇文章。由于一直忙没时间整理,最近看到了这个比较热的题,决定把这篇文章整理下。

const a = {
  i: 1,
  toString: function () {
    return a.i++;
  }
}
if (a == 1 >> a == 2 >> a == 3) {
  console.log('hello world!');
}

网上给出了很多不错的解析过程,读了下面内容,你将更深入的了解其执行过程。

1、js数据类型

js中有7种数据类型,可以分为两类:原始类型、对象类型:

基础类型(原始值):

Undefined、 Null、 String、 Number、 Boolean、 Symbol (es6新出的,本文不讨论这种类型)

复杂类型(对象值):

object

2、三种隐式转换类型

js中一个难点就是js隐形转换,因为js在一些操作符下其类型会做一些变化,所以js灵活,同时造成易出错,并且难以理解。

涉及隐式转换最多的两个运算符 + 和 ==。

+运算符即可数字相加,也可以字符串相加。所以转换时很麻烦。== 不同于===,故也存在隐式转换。- * / 这些运算符只会针对number类型,故转换的结果只能是转换成number类型。

既然要隐式转换,那到底怎么转换呢,应该有一套转换规则,才能追踪最终转换成什么了。

隐式转换中主要涉及到三种转换:

1、将值转为原始值,ToPrimitive()。

2、将值转为数字,ToNumber()。

3、将值转为字符串,ToString()。

2.1、通过ToPrimitive将值转换为原始值

js引擎内部的抽象操作ToPrimitive有着这样的签名:

ToPrimitive(input, PreferredType?)

input是要转换的值,PreferredType是可选参数,可以是Number或String类型。他只是一个转换标志,转化后的结果并不一定是这个参数所值的类型,但是转换结果一定是一个原始值(或者报错)。

2.1.1、如果PreferredType被标记为Number,则会进行下面的操作流程来转换输入的值。

1、如果输入的值已经是一个原始值,则直接返回它
2、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,
   如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
3、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。

2.1.2、如果PreferredType被标记为String,则会进行下面的操作流程来转换输入的值。

1、如果输入的值已经是一个原始值,则直接返回它
2、否则,调用这个对象的toString()方法,如果toString()方法返回的是一个原始值,则返回这个原始值。
3、否则,如果输入的值是一个对象,则调用该对象的valueOf()方法,
   如果valueOf()方法的返回值是一个原始值,则返回这个原始值。
4、否则,抛出TypeError异常。

既然PreferredType是可选参数,那么如果没有这个参数时,怎么转换呢?PreferredType的值会按照这样的规则来自动设置:

1、该对象为Date类型,则PreferredType被设置为String
2、否则,PreferredType被设置为Number

2.1.3、valueOf方法和toString方法解析

上面主要提及到了valueOf方法和toString方法,那这两个方法在对象里是否一定存在呢?答案是肯定的。在控制台输出Object.prototype,你会发现其中就有valueOf和toString方法,而Object.prototype是所有对象原型链顶层原型,所有对象都会继承该原型的方法,故任何对象都会有valueOf和toString方法。

先看看对象的valueOf函数,其转换结果是什么?对于js的常见内置对象:Date, Array, Math, Number, Boolean, String, Array, RegExp, Function。

1、Number、Boolean、String这三种构造函数生成的基础值的对象形式,通过valueOf转换后会变成相应的原始值。如:

var num = new Number('123');
num.valueOf(); // 123
var str = new String('12df');
str.valueOf(); // '12df'
var bool = new Boolean('fd');
bool.valueOf(); // true

2、Date这种特殊的对象,其原型Date.prototype上内置的valueOf函数将日期转换为日期的毫秒的形式的数值。

var a = new Date();
a.valueOf(); // 1515143895500
3、除此之外返回的都为this,即对象本身:(有问题欢迎告知)
var a = new Array();
a.valueOf() === a; // true
var b = new Object({});
b.valueOf() === b; // true
再来看看toString函数,其转换结果是什么?对于js的常见内置对象:Date, Array, Math, Number, Boolean, String, Array, RegExp, Function。

1、Number、Boolean、String、Array、Date、RegExp、Function这几种构造函数生成的对象,通过toString转换后会变成相应的字符串的形式,因为这些构造函数上封装了自己的toString方法。如:

Number.prototype.hasOwnProperty('toString'); // true
Boolean.prototype.hasOwnProperty('toString'); // true
String.prototype.hasOwnProperty('toString'); // true
Array.prototype.hasOwnProperty('toString'); // true
Date.prototype.hasOwnProperty('toString'); // true
RegExp.prototype.hasOwnProperty('toString'); // true
Function.prototype.hasOwnProperty('toString'); // true
var num = new Number('123sd');
num.toString(); // 'NaN'
var str = new String('12df');
str.toString(); // '12df'
var bool = new Boolean('fd');
bool.toString(); // 'true'
var arr = new Array(1,2);
arr.toString(); // '1,2'
var d = new Date();
d.toString(); 
var func = function () {}
func.toString(); // function () {}

除这些对象及其实例化对象之外,其他对象返回的都是该对象的类型,(有问题欢迎告知),都是继承的Object.prototype.toString方法。

var obj = new Object({});
obj.toString();
Math.toString();

从上面valueOf和toString两个函数对对象的转换可以看出为什么对于ToPrimitive(input, PreferredType?),PreferredType没有设定的时候,除了Date类型,PreferredType被设置为String,其它的会设置成Number。

因为valueOf函数会将Number、String、Boolean基础类型的对象类型值转换成 基础类型,Date类型转换为毫秒数,其它的返回对象本身,而toString方法会将所有对象转换为字符串。显然对于大部分对象转换,valueOf转换更合理些,因为并没有规定转换类型,应该尽可能保持原有值,而不应该想toString方法一样,一股脑将其转换为字符串。

所以对于没有指定PreferredType类型时,先进行valueOf方法转换更好,故将PreferredType设置为Number类型。

而对于Date类型,其进行valueOf转换为毫秒数的number类型。在进行隐式转换时,没有指定将其转换为number类型时,将其转换为那么大的number类型的值显然没有多大意义。(不管是在+运算符还是==运算符)还不如转换为字符串格式的日期,所以默认Date类型会优先进行toString转换。故有以上的规则:

PreferredType没有设置时,Date类型的对象,PreferredType默认设置为String,其他类型对象PreferredType默认设置为Number。

2.2、通过ToNumber将值转换为数字

根据参数类型进行下面转换:参数结果undefinedNaNnull+0布尔值true转换1,false转换为+0数字无须转换字符串有字符串解析为数字,例如:‘324’转换为324,‘qwer’转换为NaN对象(obj)先进行 ToPrimitive(obj, Number)转换得到原始值,在进行ToNumber转换为数字

2.3、通过ToString将值转换为字符串

根据参数类型进行下面转换:参数结果undefined’undefined’null’null’布尔值转换为’true’ 或 ‘false’数字数字转换字符串,比如:1.765转为’1.765’字符串无须转换对象(obj)先进行 ToPrimitive(obj, String)转换得到原始值,在进行ToString转换为字符串讲了这么多,是不是还不是很清晰,先来看看一个例子:

({} + {}) = ?
两个对象的值进行+运算符,肯定要先进行隐式转换为原始类型才能进行计算。
1、进行ToPrimitive转换,由于没有指定PreferredType类型,{}会使默认值为Number,进行ToPrimitive(input, Number)运算。
2、所以会执行valueOf方法,({}).valueOf(),返回的还是{}对象,不是原始值。
3、继续执行toString方法,({}).toString(),返回[object Object],是原始值。


再来一个指定类型的例子:

2 * {} = ?1、首先*运算符只能对number类型进行运算,故第一步就是对{}进行ToNumber类型转换。2、由于{}是对象类型,故先进行原始类型转换,ToPrimitive(input, Number)运算。3、所以会执行valueOf方法,({}).valueOf(),返回的还是{}对象,不是原始值。4、继续执行toString方法,({}).toString(),返回[object Object],是原始值。5、转换为原始值后再进行ToNumber运算,[object Object]就转换为NaN。故最终的结果为 2 * NaN = NaN


## 3、== 运算符隐式转换
== 运算符的规则规律性不是那么强,按照下面流程来执行,es5文档
比较运算 x==y, 其中 x 和 y 是值,返回 true 或者 false。这样的比较按如下方式进行:1、若 Type(x) 与 Type(y) 相同, 则

  1* 若 Type(x) 为 Undefined, 返回 true。
  2* 若 Type(x) 为 Null, 返回 true。
  3* 若 Type(x) 为 Number, 则

      (1)、若 x 为 NaN, 返回 false。
      (2)、若 y 为 NaN, 返回 false。
      (3)、若 x 与 y 为相等数值, 返回 true。
      (4)、若 x 为 +0 且 y 为 −0, 返回 true。
      (5)、若 x 为 −0 且 y 为 +0, 返回 true。
      (6)、返回 false。

  4* 若 Type(x) 为 String, 则当 x 和 y 为完全相同的字符序列(长度相等且相同字符在相同位置)时返回 true。 否则, 返回 false。
  5* 若 Type(x) 为 Boolean, 当 x 和 y 为同为 true 或者同为 false 时返回 true。 否则, 返回 false。
  6*  当 x 和 y 为引用同一对象时返回 true。否则,返回 false。

2、若 x 为 null 且 y 为 undefined, 返回 true。3、若 x 为 undefined 且 y 为 null, 返回 true。4、若 Type(x) 为 Number 且 Type(y) 为 String,返回比较 x == ToNumber(y) 的结果。5、若 Type(x) 为 String 且 Type(y) 为 Number,返回比较 ToNumber(x) == y 的结果。6、若 Type(x) 为 Boolean, 返回比较 ToNumber(x) == y 的结果。7、若 Type(y) 为 Boolean, 返回比较 x == ToNumber(y) 的结果。8、若 Type(x) 为 String 或 Number,且 Type(y) 为 Object,返回比较 x == ToPrimitive(y) 的结果。9、若 Type(x) 为 Object 且 Type(y) 为 String 或 Number, 返回比较 ToPrimitive(x) == y 的结果。10、返回 false。


上面主要分为两类,x、y类型相同时,和类型不相同时。

类型相同时,没有类型转换,主要注意NaN不与任何值相等,包括它自己,即NaN !== NaN。

类型不相同时,

1、x,y 为null、undefined两者中一个 // 返回true

2、x、y为Number和String类型时,则转换为Number类型比较。

3、有Boolean类型时,Boolean转化为Number类型比较。

4、一个Object类型,一个String或Number类型,将Object类型进行原始转换后,按上面流程进行原始值比较。

### 3.1、== 例子解析

所以类型不相同时,可以会进行上面几条的比较,比如:
var a = { valueOf: function () { return1; }, toString: function () { return'123' }}true == a // true;首先,x与y类型不同,x为boolean类型,则进行ToNumber转换为1,为number类型。接着,x为number,y为object类型,对y进行原始转换,ToPrimitive(a, ?),没有指定转换类型,默认number类型。而后,ToPrimitive(a, Number)首先调用valueOf方法,返回1,得到原始类型1。最后 1 == 1, 返回true。

我们再看一段很复杂的比较,如下:
[] == !{}//1、! 运算符优先级高于==,故先进行!运算。2、!{}运算结果为false,结果变成 [] == false比较。3、根据上面第7条,等式右边y = ToNumber(false) = 0。结果变成 [] == 0。4、按照上面第9条,比较变成ToPrimitive([]) == 0。 按照上面规则进行原始值转换,[]会先调用valueOf函数,返回this。 不是原始值,继续调用toString方法,x = [].toString() = ''。 故结果为 '' == 0比较。5、根据上面第5条,等式左边x = ToNumber('') = 0。 所以结果变为: 0 == 0,返回true,比较结束。

最后我们看看文章开头说的那道题目:
const a = { i: 1, toString: function () { return a.i++; }}if (a == 1 && a == 2 && a == 3) { console.log('hello world!');}

1、当执行a == 1 >> a == 2 >> a == 3 时,会从左到右一步一步解析,首先 a == 1,会进行上面第9步转换。ToPrimitive(a, Number) == 1。

2、ToPrimitive(a, Number),按照上面原始类型转换规则,会先调用valueOf方法,a的valueOf方法继承自Object.prototype。返回a本身,而非原始类型,故会调用toString方法。

3、因为toString被重写,所以会调用重写的toString方法,故返回1,注意这里是i++,而不是++i,它会先返回i,在将i+1。故ToPrimitive(a, Number) = 1。也就是1 == 1,此时i = 1 + 1 = 2。

4、执行完a == 1返回true,会执行a == 2,同理,会调用ToPrimitive(a, Number),同上先调用valueOf方法,在调用toString方法,由于第一步,i = 2此时,ToPrimitive(a, Number) = 2, 也就是2 == 2, 此时i = 2 + 1。

5、同上可以推导 a == 3也返回true。故最终结果 a == 1 >> a == 2 >> a == 3返回true

其实了解了以上隐形转换的原理,你有没有发现这些隐式转换并没有想象中那么难。

转自:https://mp.weixin.qq.com/s?__biz=MjM5MTA1MjAxMQ==>mid=2651227769>idx=1>sn=617160e64d2be13169b1b8f4506d8801>chksm=bd495ffd8a3ed6eb226d4ef193ff2ce3958d2d03d1f3047b635915f8215af40996c2f64d5c20>scene=38#wechat_redirect

mongoose连接数据库查询不到数据

2017-11-16 20:25 我说呢

本来兴高采烈的打算用下mongoose,没想到初体验印象这么不好

代码找了好几遍问题,都开始怀疑人生了。然后就各种搜资料,没想到网上也有人问这种问题,哈哈

然后就找到了这种问题的根源:

mongoose always add an s to the end of my collection name

WTF

知道根源后解决就好办了

1.把查询数据的collection加上一个s,然后在model里面别加s

2.当然还有第二种方法,就是强制让他使用某个collection

var dataSchema = new Schema({..}, { collection: 'data' })

问题解决了,不过还是禁不住想吐槽下。

location.replace not work in Android

2017-11-09 20:16 我说呢

location.replace()方法以给定的URL来替换当前的资源。 与assign() 方法 不同的是调用replace()方法后,当前页面不会保存到会话历史中(session History),这样用户点击回退按钮将不会再跳转到该页面。

这是MDN web docs对replace的解释,其实还挺权威的,不过表现不是那么权威啊,在android里面还是会保存到会话历史中(在IOS设备上OK)...

直接上解决方法吧:

function locationReplace (url) {
    if (history.replaceState) {
        history.replaceState(null, document.title, url);
        history.go(0);
    }
    else {
        location.replace(url);
    }
}

简单粗暴.

降龙十八掌

打完收工.