闭包的定义-理解-内存模型-内存泄露
JavaScript中函数是一等公民
- 那么就意味着函数的使用是非常灵活的
- 函数可以作为另外一个函数的参数,也可以作为另外一个函数的返回值来使用
函数作为一等公民
- 函数作为参数的使用
function foo(arg) {
console.log("foo", arg);
}
foo(123);
// foo 123
// 将函数作为另外一个函数的参数
function foo(aaaa) {
aaaa();
}
function bar() {
console.log("bar");
}
foo(bar);
// bar
function calc(num1, num2, calcFn) {
console.log(calcFn(num1, num2));
}
function add(num1, num2) {
return num1 + num2;
}
function sub(num1, num2) {
return num1 - num2;
}
function mul(num1, num2) {
return num1 * num2;
}
var m = 20;
var n = 30;
calc(m, n, add);
calc(m, n, sub);
calc(m, n, mul);
// 50
// -10
// 600
函数作为返回值的使用
// JavaScript语法允许函数内部再定义函数
function foo() {
function bar() {
console.log("bar");
}
return bar;
}
var fn = foo();
fn();
// bar
function makeAdder(count) {
function add(num) {
return count + num;
}
return add;
}
var add5 = makeAdder(5);
console.log(add5(6));
console.log(add5(10));
// 11
// 15
高阶函数
- 把一个函数如果接收另外一个函数作为参数,或者该函数会返回另外一个函数作为返回值的函数,那么这个函数就称之为是一个高阶函数
数组中的函数使用
var nums = [10, 5, 11, 100, 55];
var newNums = [];
for (var i = 0; i < nums.length; i++) {
var num = nums[i];
if (num % 2 === 0) {
newNums.push(num);
}
}
console.log(newNums);
// [ 10, 100 ]
函数
- 独立的function,那么称之为是一个函数
方法
- 当我们的一个函数属于一个对象时,我们称这个函数是这个对象的方法
函数和方法的区别
// 函数function - 独立的function,那么称之为是一个函数
function foo() {}
// 方法method - 当我们的一个函数属于一个对象时,我们称这个函数是这个对象的方法
var obj = {
foo: function () {}
};
obj.foo();
filter
var nums = [10, 5, 11, 100, 55];
// filter过滤
var newNums = nums.filter(item => item % 2 === 0);
console.log(newNums);
// [ 10, 100 ]
var nums = [10, 5, 11, 100, 55];
var newNums = nums.filter(function (item) {
return false;
});
console.log(newNums);
// []
var nums = [10, 5, 11, 100, 55];
var newNums = nums.filter(function (item) {
return true;
});
console.log(newNums);
// [ 10, 5, 11, 100, 55 ]
var nums = [10, 5, 11, 100, 55];
var newNums = nums.filter(function (item) {
return item % 2 === 0;
});
console.log(newNums);
// [ 10, 100 ]
var nums = [10, 5, 11, 100, 55];
var newNums2 = nums.map(function (item) {
return item;
});
console.log(newNums2);
// [ 10, 5, 11, 100, 55 ]
map
var nums = [10, 5, 11, 100, 55];
var newNums2 = nums.map(function (item) {
return item;
});
console.log(newNums2);
// [ 10, 5, 11, 100, 55 ]
var nums = [10, 5, 11, 100, 55];
var newNums2 = nums.map(function (item) {
return item * 10;
});
console.log(newNums2);
// [ 100, 50, 110, 1000, 550 ]
forEach
// forEach
var nums = [10, 5, 11, 100, 55];
nums.forEach(function (item) {
console.log(item);
});
// 10
// 5
// 11
// 100
// 55
find
// find
var nums = [10, 5, 11, 100, 55];
var item = nums.find(function (item) {
return true;
});
console.log(item);
// 10
// find
var nums = [10, 5, 11, 100, 55];
var item = nums.find(function (item) {
return item === 100;
});
console.log(item);
// 100
var friends = [
{ name: "why", age: 18 },
{ name: "kobe", age: 40 },
{ name: "james", age: 35 },
{ name: "curry", age: 30 }
];
const findFriend = friends.find(function (item) {
return item.name === "james";
});
console.log(findFriend);
// { name: 'james', age: 35 }
findIndex
var friends = [
{ name: "why", age: 18 },
{ name: "kobe", age: 40 },
{ name: "james", age: 35 },
{ name: "curry", age: 30 }
];
const findFriend = friends.find(function (item) {
return item.name === "james";
});
console.log(findFriend);
var friendIndex = friends.findIndex(function (item) {
return item.name === "james";
});
console.log(friendIndex);
// { name: 'james', age: 35 }
// 2
reduce
var nums = [10, 5, 11, 100, 55];
var total = 0;
for (var i = 0; i < nums.length; i++) {
total += nums[i];
}
console.log(total);
// 181
// reduce
var nums = [10, 5, 11, 100, 55];
var sum = nums.reduce(function (preValue, item) {
return preValue + item;
}, 0);
console.log(sum);
// 181
闭包
维基百科的定义
- 闭包又称词法闭包或者函数闭包
- 是在支持头等函数的编程语言中,实现词法绑定的一种技术
- 闭包在实现上是一个结构体,它存储了一个函数和一个关联的环境
- 闭包跟函数最大的区别在于,当捕获闭包的时候,他的自由变量会在捕捉时被确定,这样即使脱离了捕捉时的上下文,他也能照常运行
MDN的定义
- 一个函数和对其周围状态的引用捆绑在一起,这样的组合就是闭包
- 也就说,闭包让你可以在一个内层函数中访问到其外层函数的作用域
- 在JavaScript中,每当创建一个函数,闭包就会在函数创建的同时被创建出来
个人理解
- 一个普通的函数function,如果它可以访问外层作用域的自由变量,那么这个函数就是一个闭包
高阶函数执行过程
function foo() {
function bar() {
console.log("bar");
}
return bar;
}
var fn = foo();
fn();
// bar
function foo() {
function bar() {
console.log("bar");
}
return bar;
}
var fn = foo();
fn();
/**
* 编译
* var globalObject = {
* String: "类",
* Date: "类",
* setTimeout: "函数",
* window: globalObject,
* foo: 0xfoo,
* fn: undefined
* }
* 执行
* var GlobalObject = {
* String: "类",
* Date: "类",
* setTimeout: "函数",
* window: GlobalObject,
* foo: 0xfoo,
* fn: 0xbar
* }
*/
// bar
闭包到底是什么
function foo() {
var name = "foo";
function bar() {
console.log("bar", name);
}
return bar;
}
var fn = foo();
fn();
/**
* 编译
* var globalObject = {
* String: "类",
* Date: "类",
* setTimeout: "函数",
* window: globalObject,
* foo: 0xfoo,
* fn: undefined
* }
* 执行
* var GlobalObject = {
* String: "类",
* Date: "类",
* setTimeout: "函数",
* window: GlobalObject,
* foo: 0xfoo,
* fn: 0xbar
* }
*/
// bar foo
函数的执行过程的内存
function foo() {
var name = "foo";
var age = 18;
}
function test() {
console.log("test");
}
foo();
test();
/**
* 编译
* var globalObject = {
* Date: "类",
* String: "类",
* Window: glabalObject,
* foo: 0xfoo,
* test: 0xtest
* }
* 执行
* var globalObject = {
* Date: "类",
* String: "类",
* Window: glabalObject,
* foo: 0xfoo,
* test: 0xtest
* }
*/
// test
函数的执行过程的内存 - 闭包
function foo() {
var name = "foo";
var age = 18;
function bar() {
console.log(name);
console.log(age);
}
return bar;
}
var fn = foo();
fn();
/**
* 编译
* var globalObject = {
* Date: "类",
* String: "类",
* Window: glabalObject,
* foo: 0xfoo,
* fn: undefined
* }
* 执行
* var globalObject = {
* Date: "类",
* String: "类",
* Window: glabalObject,
* foo: 0xfoo,
* fn: 0xbar
* }
*/
// foo
// 18
/**
* 解决内存泄漏的方法
*/
fn = null;
foo = null;