函数分为函数声明、函数表达式和构造函数
// 函数声明式
function sum(param1, param2) {
return param1 + param2;
}
let sum = function(param1, param2) {
return param1 + param2;
}
const add = new Function('a','b','return a + b')
console.log(add(1,2));
Function构造函数用得比较少,因为Function构造函数的每一次执行,都会解析函数主体,创建一个新的函数对象,如果是一个频繁调用的函数,这样效率非常低。
另一个原因是Function创建的函数一直作为顶级函数来执行,如果我们在一个函数A中调用Function构造函数,其中的函数体不能访问函数A的局部变量,如下代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
var y = 'global'; // 全局环境定义的y值
function constructFunction() {
var y = 'local'; // 局部环境定义的y值
return new Function('return y'); // 无法获取局部环境定义的值
}
console.log(constructFunction()()); // 输出'global'
</script>
</body>
</html>
arguments对象是所有函数都具有的一个内置局部变量,表示是函数实际接收的参数,arguments是一个类数组的结构。arguments对象只能在函数体内使用,如下代码:
(function (a, b) {
console.log(arguments); // [Arguments] { '0': 2 }
})(2)
arguments是表示实际参数的,所以就由实际参数决定,如上代码中,定义的形参有两个,实参却只有一个,那么arguments对象的值也只有一个。
构造函数和和普通函数的区别:
function Do(){
this.name = 'play'
}
const aa = new Do()
console.log(aa.name); // play
一个变量的定义和调用都是在一个范围内,这个范围就是作用域。
作用域分为全局作用域、函数作用域和块级作用域
全局作用域和块级作用域比较简单,这里仅仅总结一下函数作用域。
在函数内部使用var关键字声明变量的时候,函数中会存在变量提升的问题,如下代码:
(function(){
console.log(a); // undefined
var a =908;
})()
在变量a声明之前打印,输出结果为undefined。这段代码等同于:
(function(){
var a ;
console.log(a); // undefined
})()
这就是变量提升,将变量的声明提升到函数的顶部位置,但是变量的赋值并没有提升。
只有通过var关键字声明的变量才会出现提升的问题。
使用函数声明方式来定义一个函数,也会出现函数提升问题,通过函数表达式声明函数不会出现函数提升问题。
add(1, 2); // 3
function add(a, c) {
console.log(a + c)
}
闭包是一个拥有多个变量和绑定这些变量执行上下文环境的表达式,一般都是一个函数。
函数拥有外部变量的引用,在函数执行完成后,该变量没有被销毁,处于活跃状态;
当闭包作为一个函数返回的时候,它的执行上下文环境没有被销毁;
这样闭包就导致大量消耗内存,闭包使用越多,内存消耗就越大。
但是闭包也有一些有点:
var cachedBox = (function () {
// 缓存的容器
var cache = {};
return {
searchBox: function (id) {
// 如果在内存中,则直接返回
if (id in cache) {
return '查找的结果为:' + cache[id];
}
// 经过一段很耗时的dealFn()函数处理
var result = dealFn(id);
// 更新缓存的结果
cache[id] = result;
// 返回计算的结果
return '查找的结果为:' + result;
}
};
})();
// 处理很耗时的函数
function dealFn(id) {
console.log('这是一段很耗时的操作');
return id;
}
// 两次调用searchBox()函数
console.log(cachedBox.searchBox(1));
console.log(cachedBox.searchBox(1));
let stack=(
function() {
let items = [];
return {
push:function (element) {
items.push(element)
},
pop:function () {
return items.pop();
},
size:function () {
return items.length;
}
}
}
)()
stack.push(90);
stack.push(100);
console.log(stack.size());// 2
总结闭包的优点:
闭包缺点: