javaScript 基础知识汇总 (十)
1、New Function
语法:let
func =
new
Function
(
[
arg1[
,
arg2[
,
...
argN]
]
,
]
functionBody)
//无参数示例:
let sayHi = new Function('alert ("Hello")');
sayHi();//Hello
//有参数示例
let sum = new Function('a','b','return a + b');
alert(sum(1,2));//3
2、调度:setTimeout 和 setInterval
setTimeout 将函数的执行推迟到一段时间后再执行
setInterval 让函数间隔一定时间周期性执行
setTimeout 语法:let
timerId =
setTimeout
(
func|
code,
delay[
,
arg1,
arg2...
]
)
func|code 想要执行的代码或者代码字符串
delay:执行前的延时 单位为毫秒
arg1,arg2..:参数列表,ie9 以下不支持
无参数示例
function sayHi(){
alert('hello');
}
setTimeout(sayHi,1000);//1秒后执行
带参数示例
function sayHi(pthrase,who){
alert(phrase+','+who);
}
setTimeou(sayHi,1000,"Hello","Jhon");//Hello,John
箭头函数的形式
setTimeout(()=>alert('hello'));
用claerTimeout 来取消调度
setTimeout 在调用时会返回一个定时器id
cleatTimeout 使用的方法
let timerId = setTimeout(....);
clearTimeout(timerId);
示例:
1 let timerId = setTimeout(() => alert("never happens"), 1000); 2 alert(timerId); // 定时器 id 3 4 clearTimeout(timerId); 5 alert(timerId); // 还是那个 id 没变(并没有因为调度被取消了而变成 null)
setInterval
语法: let timerId = setInterVal(func|code,delay,[,arg1,arg2...])
用法和setTimeout 相同,但是执行的方式不一样,这个是每间隔相同的时间执行一次。
递归版 setTimeout
1 let i = 1; 2 setInterval(function() { 3 func(i); 4 }, 100); 5 6 let i = 1; 7 setTimeout(function run() { 8 func(i); 9 setTimeout(run, 100); 10 }, 100);
setTimeout(...,0);
这种用法,虽然时间为0,但是还是会被延时执行,放到一般函数后执行
3、装饰和转发,call/apply
1) 使用“func.call" 作为上下文
语法: func.call(context,arg1,arg2,...)
1 function sayHi() { 2 alert(this.name); 3 } 4 5 let user = { name: "John" }; 6 let admin = { name: "Admin" }; 7 8 // 使用 call 将不同的对象传递为 "this" 9 sayHi.call( user ); // this = John 10 sayHi.call( admin ); // this = Admin
1 function say(phrase) { 2 alert(this.name + ': ' + phrase); 3 } 4 5 let user = { name: "John" }; 6 7 // user becomes this, and "Hello" becomes the first argument 8 say.call( user, "Hello" ); // John: Hello
1 let worker = { 2 someMethod() { 3 return 1; 4 }, 5 6 slow(x) { 7 alert("Called with " + x); 8 return x * this.someMethod(); // (*) 9 } 10 }; 11 12 function cachingDecorator(func) { 13 let cache = new Map(); 14 return function(x) { 15 if (cache.has(x)) { 16 return cache.get(x); 17 } 18 let result = func.call(this, x); // "this" 现在被正确的传递了 19 cache.set(x, result); 20 return result; 21 }; 22 } 23 24 worker.slow = cachingDecorator(worker.slow); // 现在让他缓存起来 25 26 alert( worker.slow(2) ); // 生效了 27 alert( worker.slow(2) ); // 生效了, 不会调用原始的函数了。被缓存起来了 28 29 为了清楚地说明,让我们更深入地了解 this 是如何传递的: 30 在经过装饰之后,worker.slow 现在是包装器 function (x) { ... }。 31 因此,当执行 worker.slow(2) 时,包装器将 2 作为参数并且 this=worker(它是点之前的对象)。 32 在包装器内部,假设结果尚未缓存,func.call(this, x) 将当前的 this (=worker) 和当前参数 (=2)
传递给原始方法。
2)使用"func.apply" 来传递多参数
语法:func.apply(context,args)
1 function say(time, phrase) { 2 alert(`[${time}] ${this.name}: ${phrase}`); 3 } 4 5 let user = { name: "John" }; 6 7 let messageData = ['10:00', 'Hello']; // 成为时间和短语 8 9 // user 成为 this,messageData 作为参数列表传递 (time, phrase) 10 say.apply(user, messageData); // [10:00] John: Hello (this=user)
4、函数绑定
丢失this
在JavaScript中this很容易就会丢失。一旦一个方法被传递到另一个对象分离的地方-----this就会丢失
丢失示例:
let user = {
firstName:"Jhon",
sayHi(){
alert(`Hello,${this.firstName}!`);
}
};
setTimeout(user.sayHi,1000);//Hello,undefined!
这种情况下上下文丢失
解决方案一:包装层
let user = {
firstName:"John",
sayHi(){
alert(`Hello,${this.firstName}!`);
}
};
setTimeout(function(){
user.sayHi();//Hello,Jhon!
},1000);
这种方式存在一种风险,就是在1秒之内如果user被改之后,操作的user可能就不是之前的
解决方案二:bind
基本的语法: let boundFunc = func.bind(context);
func.bind(context)
的结果是一个特殊的像函数一样的“外来对象”,它可以像函数一样被调用并且透明的将 调用传递给 func
并设置 this=context
。
换句话说,调用 boundFunc
就像是调用 func
并且固定住了 this
。
举个例子,这里 funcUser
将调用传递给了 func
同时 this=user
:
1 let user = { 2 firstName: "John" 3 }; 4 5 function func() { 6 alert(this.firstName); 7 } 8 9 let funcUser = func.bind(user); 10 funcUser(); // John
处理对象的方法
1 let user = { 2 firstName: "John", 3 sayHi() { 4 alert(`Hello, ${this.firstName}!`); 5 } 6 }; 7 8 let sayHi = user.sayHi.bind(user); // (*) 9 10 sayHi(); // Hello, John! 11 12 setTimeout(sayHi, 1000); // Hello, John!