面试题-前端开发JavaScript篇下(答案超详细)

实现一个 once 函数,传入函数参数只执行一次

function ones(func) {
	var tag = true;
	return function() {
		if (tag == true) {
			func.apply(null, arguments);
			tag = false;
		}
		return undefined
	}
}

将原生的 ajax 封装成 promis

var myNewAjax = function(url) {
	return new Promise(function(resolve, reject) {
		var xhr = new XMLHttpRequest();
		xhr.open('get', url);
		xhr.send(data);
		xhr.onreadystatechange = function() {
			if (xhr.status == 200 && readyState == 4) {
				var json = JSON.parse(xhr.responseText);
				resolve(json)
			} else if (xhr.readyState == 4 && xhr.status != 200) {
				reject('error');
			}
		}
	})
}

JS 监听对象属性的改变

//我们假设这里有一个 user 对象, (1) 在 ES5 中可以通过 Object.defineProperty 来实现已有属性的监听
Object.defineProperty(user, 'name', {
	setfunction(key, value) {}
})
//缺点: 如果 id 不在 user 对象中, 则不能监听 id 的变化
	(2)ES6 中可以通过 Proxy 来实现
var user = new Proxy({}{
	setfunction(target, key, value, receiver) {}
})
//这样即使有属性在 user 中不存在, 通过 user.id 来定义也同样可以这样监听这个属性的变化哦。

如何实现一个私有变量,用 getName 方法可以访问,不能直接访问

// (1)通过 defineProperty 来实现
obj = {
	name: yuxiaoliang,
	getName: function() {
		return this.name
	}
}
object.defineProperty(obj, "name", {
	//不可枚举不可配置
});
// (2)通过函数的创建形式
function product() {
	var name = 'yuxiaoliang';
	this.getName = function() {
		return name;
	}
}
var obj = new product();

=、以及 Object.is 的区别

//(1) == 主要存在:强制转换成 number,null==undefined
" "==0 //true
"0"==0 //true
" " !="0" //true
123=="123" //true
null==undefined //true
//(2)Object.js
主要的区别就是+0=-0NaN==NaN
(相对比=====的改进)

setTimeout、setInterval 和 requestAnimationFrame 之间的区别

这里有一篇文章讲的是 requestAnimationFrame:
http://www.cnblogs.com/xiaohuochai/p/5777186.html
与 setTimeout 和 setInterval 不同,requestAnimationFrame 不需要设置时间间隔,
大多数电脑显示器的刷新频率是 60Hz,大概相当于每秒钟重绘 60 次。大多数浏览器都
会对重绘操作加以限制,不超过显示器的重绘频率,因为即使超过那个频率用户体验也
不会有提升。因此,最平滑动画的最佳循环间隔是 1000ms/60,约等于 16.6ms。
RAF 采用的是系统时间间隔,不会因为前面的任务,不会影响 RAF,但是如果前面的
任务多的话,
会响应 setTimeout 和 setInterval 真正运行时的时间间隔。
特点:
(1)requestAnimationFrame 会把每一帧中的所有 DOM 操作集中起来,在一次重绘或回
流中就完成,并且重绘或回流的时间间隔紧紧跟随浏览器的刷新频率。
(2)在隐藏或不可见的元素中,requestAnimationFrame 将不会进行重绘或回流,这当然
就意味着更少的 CPU、GPU 和内存使用量
(3)requestAnimationFrame 是由浏览器专门为动画提供的 API,在运行时浏览器会自动
优化方法的调用,并且如果页面不是激活状态下的话,动画会自动暂停,有效节省了
CPU 开销

实现一个两列等高布局,讲讲思路

为了实现两列等高,可以给每列加上 padding-bottom:9999px;
margin-bottom:-9999px;同时父元素设置 overflow:hidden;

自己实现一个 bind 函数

// 原理:通过 apply 或者 call 方法来实现。
// (1)初始版本
Function.prototype.bind = function(obj, arg) {
	var arg = Array.prototype.slice.call(arguments, 1);
	var context = this;
	return function(newArg) {
		arg = arg.concat(Array.prototype.slice.call(newArg));
		return context.apply(obj, arg);
	}
}
// (2) 考虑到原型链
// 为什么要考虑?因为在 new 一个 bind 过生成的新函数的时候,必须的条件是要继承原函数的原型
Function.prototype.bind = function(obj, arg) {
	var arg = Array.prototype.slice.call(arguments, 1);
	var context = this;
	var bound = function(newArg) {
		arg = arg.concat(Array.prototype.slice.call(newArg));
		return context.apply(obj, arg);
	}
	var F = function() {}
	//这里需要一个寄生组合继承
	F.prototype = context.prototype;
	bound.prototype = new F();
	return bound;
}

用 setTimeout 来实现 setInterval

(1)用 setTimeout()方法来模拟 setInterval()与 setInterval()之间的什么区别?
首先来看 setInterval 的缺陷,使用 setInterval()创建的定时器确保了定时器代码规则地插
入队列中。这个问题在于:如果定时器代码在代码再次添加到队列之前还没完成执行,
结果就会导致定时器代码连续运行好几次。而之间没有间隔。不过幸运的是:javascript
引擎足够聪明,能够避免这个问题。当且仅当没有该定时器的如何代码实例时,才会将
定时器代码添加到队列中。这确保了定时器代码加入队列中最小的时间间隔为指定时间。
这种重复定时器的规则有两个问题:1.某些间隔会被跳过 2.多个定时器的代码执行时间
可能会比预期小。
下面举例子说明:
假设,某个 onclick 事件处理程序使用啦 setInterval()来设置了一个 200ms 的重复定时器。
如果事件处理程序花了 300ms 多一点的时间完成。
在这里插入图片描述

这个例子中的第一个定时器是在 205ms 处添加到队列中,但是要过 300ms 才能执行。在
405ms 又添加了一个副本。在一个间隔,605ms 处,第一个定时器代码还在执行中,而
且队列中已经有了一个定时器实例,结果是 605ms 的定时器代码不会添加到队列中。结
果是在 5ms 处添加的定时器代码执行结束后,405 处的代码立即执行。

function say() {
	//something
	setTimeout(say, 200);
}
setTimeout(say, 200)
或者
setTimeout(function() {
	//do something
	setTimeout(arguments.callee, 200);
}, 200);

JS 怎么控制一次加载一张图片,加载完后再加载下一张

方法1

<script type="text/javascript">
var obj=new Image();
obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg";
obj.onload=function(){
alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height);
document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />";
}
</script>
<div id="mypic">onloading……</div>

方法2

<script type="text/javascript">
var obj=new Image();
obj.src="http://www.phpernote.com/uploadfiles/editor/201107240502201179.jpg";
obj.onreadystatechange=function(){
if(this.readyState=="complete"){
alert('图片的宽度为:'+obj.width+';图片的高度为:'+obj.height);
document.getElementById("mypic").innnerHTML="<img src='"+this.src+"' />";
}
}
</script>
<div id="mypic">onloading……</div>

代码的执行顺序

setTimeout(function() {
	console.log(1)
}, 0);
new Promise(function(resolve, reject) {
	console.log(2);
	resolve();
}).then(function() {
	console.log(3)
}).then(function() {
	console.log(4)
});
process.nextTick(function() {
	console.log(5)
});
console.log(6);

//输出 2,6,5,3,4,1
为什么呢?具体请参考这篇文章
从promise、process.nextTick、setTimeout出发,谈谈Event Loop中的Job queue

如何实现 sleep 的效果(es5 或者 es6)

(1)while 循环的方式

function sleep(ms){
var start=Date.now(),expire=start+ms;
while(Date.now()<expire);
console.log('1111');
return;
}

执行 sleep(1000)之后,休眠了 1000ms 之后输出了 1111。上述循环的方式缺点很明显,
容易造成死循环。

(2)通过 promise 来实现

function sleep(ms){
var temple=new Promise(
(resolve)=>{
console.log(111);setTimeout(resolve,ms)
});
return temple
}
sleep(500).then(function(){
//console.log(222)
})

//先输出了 111,延迟 500ms后输出222

(3)通过 async 封装

function sleep(ms) {
	return new Promise((resolve) => setTimeout(resolve, ms));
}
async function test() {
	var temple = await sleep(1000);
	console.log(1111)
	return temple
}
test();

//延迟 1000ms 输出了 1111

(4).通过 generate 来实现

function* sleep(ms) {
	yield new Promise(function(resolve, reject) {
		console.log(111);
		setTimeout(resolve, ms);
	})
}
sleep(500).next().value.then(function() {
	console.log(2222)
})

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

猿与禅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值