/**1**/
var start = new Date();
setTimeout(function() {
console.log(new Date() - start);
}, 500);
while((new Date() - start) <= 1000){}
输出:?
// (不看下面那段代码 输出: >=500) 进程和线程:计算完后需要渲染时间
while((new Date() - start) <= 1000){} // 1000ms内死循环,没有含义但是在吃CPU
// js本身是单线程,1000ms内一直占用着线程,只有主线程空了才会执行任务队列,所以最后输出 >= 1000
/**2**/
var log = console.log;
var hint = window.alert;
var write = document.write;
log('123');
hint('123');
write('123');
// 分别输出什么?
// 123
// 123
// Uncaught TypeError: Illegal invocation
// write不是window方法,所以调用会报错
var document = {
write: function(htmlText) {
if (!(this instanceof document)) {
throw new TypeError("Illegal invocation");
}
this.body.appendChild(document.createTextNode(htmlText));
}
}
// 以上是伪代码,用于理解含义
腾讯面试题
var name = "A";
function getName() {
return this.name;
}
var obj = {
name: "B",
getName: function(){
return this.name;
},
showName: function(a) {
console.log(getName());
console.log(a());
console.log(this.getName());
console.log(arguments[0]());
}
}
obj.showName(getName, 1);
// 输出 A A B undefined
// arguments 的this里没有name,所以输出undefined
console.log(arguments[0].call(window)); // 这样输出 A
据说是小米面试题
// 说出以下函数的作用是?空白区域应该填写什么?
(function (window) {
function fn(str) {
this.str = str;
}
fn.prototype.format = function () {
var arg = ______;
return this.str.replace(______, function (a, b) {
return arg[b] || "";
});
}
window.fn = fn;
})(this);
//user
(function () {
var t = new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>');
console.log(t.format('http://www.alibaba.com','Alibaba','Welcome'));
})();
答案:
(function (window) {
function fn(str) { // 构造函数 str = '<p><a href="{0}">{1}</a><span>{2}</span></p>'
this.str = str; // this.str t.str
}
fn.prototype.format = function () { // 实例对象 封装format方法
var arg = arguments;
return this.str.replace(/^\{(\d+)\}$/g, function (a, b) { //{0} {1} {2}
return arg[b] || ""; // a:正则模式 b:此正则模式中的表达式 0 1 2
});
}
window.fn = fn;
})(this);
//user
(function () {
var t = new fn('<p><a href="{0}">{1}</a><span>{2}</span></p>'); // 创建实例对象
console.log(t.format('http://www.alibaba.com','Alibaba','Welcome'));
})();
来自国外的一道题
JavaScript (a ==1 && a== 2 && a==3) 可能为 true 吗???
/* 这是国外一位求职者在最近一家大型科技公司面试时遇到的一个问题,他的回答是「不可能」
* 而面试官说「nothing is impossible」,这个问题在 Stack Overflow 上提出后,短短 3 天,访问量和答案让人很是惊喜
*/
// 答案1:
const a = {
i: 1,
toString: function () {
return a.i++;
}
}
if(a == 1 && a == 2 && a == 3) {
console.log('Hello World!');
}
// 答案2:
var i = 0;
with({
get a() {
return ++i;
}
}) {
if (a == 1 && a == 2 && a == 3) {
console.log("wohoo");
}
}
// 答案3:
a = [1,2,3];
a.join = a.shift;
console.log(a == 1 && a == 2 && a == 3);
/*
* This works because == invokes toString which calls .join for Arrays.
* Another solution, using Symbol.toPrimitive which is an ES6 equivalent of toString/valueOf:
*/
let a = {[Symbol.toPrimitive]: ((i) => () => ++i) (0)};
console.log(a == 1 && a == 2 && a == 3);
// 答案4
var val = 0;
Object.defineProperty(window, 'a', {
get: function() {
return ++val;
}
});
if (a === 1 && a === 2 && a === 3) {
console.log('yay');
}
// 这个做法可以用全等号
// https://stackoverflow.com/questions/48270127/can-a-1-a-2-a-3-ever-evaluate-to-true
一道经典面试题:
function Foo() {
getName = function () {
alert (1);
};
return this;
}
Foo.getName = function () {
alert (2);
};
Foo.prototype.getName = function () {
alert (3);
};
var getName = function () {
alert (4);
};
function getName() {
alert (5);
}
//请写出以下输出结果:
Foo.getName();
getName();
Foo().getName();
getName();
new Foo.getName();
new Foo().getName();
new new Foo().getName();
//答案:
Foo.getName();//2
getName();//4 先查栈中有没有getName变量,如果存在并且有引用 则输出,如果栈中的变量没有引用则从堆中查找
Foo().getName();//1
getName();//1
new Foo.getName();//2
new Foo().getName();//3
new new Foo().getName();//3
// 答案说明 http://web.jobbole.com/85122/
杂
// 不用临时变量交换2个值
function swap(a, b) {
b = b - a;
a = a + b;
b = a - b;
return [a, b];
}
// 交换数组内2个下标的值
arr.splice(x - 1, 1, …arr.splice(y - 1, 1, arr[x - 1]))
1.JS数据类型有哪些?哪些是引用类型?
Undefined、Null、Boolean、Number和String。还有1种复杂的数据类型————Object
Undefined、Null、Boolean、Number都属于基本类型。Object、Array和Function则属于引用类型
console.log({}.length) // undefined
console.log(({}+{}).length) // 30
// {}+{} 为[object Object][object Object] ,对象本身没有加法操作 所以 js类型转换后变成30个字符
2.CSS优先级
ID>class>元素选择器 行内样式>内页样式>外部样式
link、:visited、:hover、:active
//这四个伪类如果对同一个元素设置同一个属性,那它们的声明顺序还有一定要求,一般都遵循“爱恨原则LVHA”(LoVe HAte)
3.前端性能优化指标:
首屏加载速度,页面加载速度,响应速度
4.移动端click :
touchstart, touchmove, touchend, 以及tappc端有mousedown, mousemove, mouseup, click
5.ajax readyState 5种状态
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
6.用递归写一个阶乘函数
function test(a){
if(a==1){
return 1;
}else{
return arguments.callee(a-1)*a
}
}
7.Promise的优点
解决了回调地狱!Promise 本质上是分离了异步数据获取和业务逻辑,从而让开发人员能专注于一个事物,而不必同时考虑业务和数据。
缺点:首先,无法取消Promise,一旦新建它就会立即执行,无法中途取消。其次,如果不设置回调函数,Promise内部抛出的错误,不会反应到外部。当处于Pending状态时,无法得知目前进展到哪一个阶段(刚刚开始还是即将完成)。
// 第一部分 数据获取和加工阶段
var getUserName = function(){
return new Promise(function(resolve,reject){
$.get('xxx.com/getUserName',function(data){
resolve(data);
});
};
var getMobile = function(userName){
return new Promise(function(resolve,reject){
$.get('xxx.com/getUserMobile?user='+userName,function(data){
resolve(data);
});
});
}
// 第二部分 业务逻辑部分
getUserName().then(function(userName){
return getMobile(userName);
}).then(function(mobile){});
8.如何解决跨域问题?
jsonp、 iframe、window.name、window.postMessage、服务器上设置代理页面
- document.domain + iframe:要求主域名相同 //只能跨子域
- JSONP(JSON with Padding):response: callback(data) //只支持 GET 请求
- 跨域资源共享CORS(XHR2):Access-Control-Allow //兼容性 IE10+
- 跨文档消息传输(HTML5):postMessage + onmessage //兼容性 IE8+
- WebSocket(HTML5):new WebSocket(url) + onmessage //兼容性 IE10+
- 服务器端设置代理请求:服务器端不受同源策略限制
9.实现bind方法
Function.prototype.bind = function (context) {
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var result = function () {
var bindArgs = Array.prototype.slice.call(arguments);
// 如果this intanceof result 为 true 代表了构造函数场景
return self.apply(this instanceof result ? this : context, args.concat(bindArgs)); // 当针对方法操作的时候一定要考虑返回值,return出去
}
result.prototype = this.prototype;
return result;
}
10.vue和react的区别
- 相同点:都支持 ssr,都有 vdom,组件化开发,实现 webComponents 规范,数据驱动等
- 不同点:vue 是双向数据流(当然为了实现单数据流方便管理组件状态,vuex 便出现了),react 是单向数据流。vue 的 vdom 是追踪每个组件的依赖关系,不会渲染整个组件树,react 每当应该状态被改变时,全部子组件都会 re-render。
组件传值:React 本身并不支持自定义事件,而Vue中子组件向父组件传递消息有两种方式:事件和回调函数,但Vue更倾向于使用事件。在React中我们都是使用回调函数的,这可能是他们二者最大的区别。
VDOM:三个 part
虚拟节点类,将真实 DOM 节点用 js 对象的形式进行展示,并提供 render 方法,将虚拟节点渲染成真实 DOM
节点 diff 比较:对虚拟节点进行 js 层面的计算,并将不同的操作都记录到 patch 对象
re-render:解析 patch 对象,进行 re-render补充1:VDOM 的必要性?
创建真实DOM的代价高:真实的 DOM 节点 node 实现的属性很多,而 vnode 仅仅实现一些必要的属性,相比起来,创建一个 vnode 的成本比较低。
触发多次浏览器重绘及回流:使用 vnode ,相当于加了一个缓冲,让一次数据变动所带来的所有 node 变化,先在 vnode 中进行修改,然后 diff 之后对所有产生差异的节点集中一次对 DOM tree 进行修改,以减少浏览器的重绘及回流。
补充2:vue 为什么采用 vdom?引入 Virtual DOM 在性能方面的考量仅仅是一方面。
性能受场景的影响是非常大的,不同的场景可能造成不同实现方案之间成倍的性能差距,所以依赖细粒度绑定及 Virtual DOM 哪个的性能更好还真不是一个容易下定论的问题。
Vue 之所以引入了 Virtual DOM,更重要的原因是为了解耦 HTML依赖,这带来两个非常重要的好处是:
不再依赖 HTML 解析器进行模版解析,可以进行更多的 AOT 工作提高运行时效率:通过模版 AOT 编译,Vue 的运行时体积可以进一步压缩,运行时效率可以进一步提升;
可以渲染到 DOM 以外的平台,实现 SSR、同构渲染这些高级特性,Weex等框架应用的就是这一特性。
综上,Virtual DOM 在性能上的收益并不是最主要的,更重要的是它使得 Vue 具备了现代框架应有的高级特性。
11.Vuex和Redux的区别
从表面上来说,store注入和使用方式有一些区别。在Vuex中,$store
被直接注入到了组件实例中,因此可以比较灵活的使用:使用dispatch、commit提交更新,通过mapState或者直接通过this.$store来读取数据。在Redux中,我们每一个组件都需要显示的用connect把需要的props和dispatch连接起来。另外,Vuex更加灵活一些,组件中既可以dispatch action,也可以commit updates,而Redux中只能进行dispatch,不能直接调用reducer进行修改。
从实现原理上来说,最大的区别是两点:Redux使用的是不可变数据,而Vuex的数据是可变的,因此,Redux每次都是用新state替换旧state,而Vuex是直接修改。Redux在检测数据变化的时候,是通过diff的方式比较差异的,而Vuex其实和Vue的原理一样,是通过getter/setter来比较的,这两点的区别,也是因为React和Vue的设计理念不同。React更偏向于构建稳定大型的应用,非常的科班化。相比之下,Vue更偏向于简单迅速的解决问题,更灵活,不那么严格遵循条条框框。因此也会给人一种大型项目用React,小型项目用Vue的感觉。
12. React内实现vue的slot功能
<Button>
<Icon name="dollars"/>
<span>BUY NOW</span>
</Button>
function Button(props) {
return (
<button>
{props.children}
</button>
);
}
children 可以被正常识别为一个 Prop 属性直接写在dom内
// This code...
<Button children={<span>Click Me</span>} />
// Is equivalent to this code...
<Button>
<span>Click Me</span>
</Button>
网友评论