文章目录
实现一个 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', {
set: function(key, value) {}
})
//缺点: 如果 id 不在 user 对象中, 则不能监听 id 的变化
(2) 在 ES6 中可以通过 Proxy 来实现
var user = new Proxy({}, {
set: function(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!=-0 而 NaN==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)
})