在JavaScript中,函数是一等公民。JavaScript是一门面向对象的编程语言,但是同时也有很多函数式编程的特性,如Lambda表达式,闭包,高阶函数等,函数式编程时一种编程范式。

function dada() {
var a = 1;
var b = function() {
console.log(a);
}
return b
// b 就是一个闭包函数,因为它能访问dada函数的作用域
}

JavaScript的函数也是对象,可以有属性,可以赋值给一个变量,可以放在数组里作为元素,可以作为其他对象的属性,什么都可以做,别的对象能做的它也能做,别的对象不能做的它也能做。

函数和其他普通对象来说,是一样的,有属性有方法,普通对象能做的,函数也能做。学习JavaScript中的闭包和高级函数是基础篇哦!

那么什么是闭包?闭包,就是有权访问其外部作用域中的变量和参数的函数。

var func = (function() {
var item = 0;
return {
add: function(num) {
item = typeof num === 'number' ? num : 1;
},
value: function() {
return item;
}
}
})();

闭包函数可以访问它创建时所处的上下文环境中的变量以及参数,this以及arguments除外。

闭包:

函数作为返回值,高阶函数除了可以接受函数作为参数外,还可以把函数作为结果值返回。闭包的形成与变量的作用于和变量的生命周期密切相关。

变量作用域:

var func = function() {
var a = 1;
console.log(a); // 1
}
func();
console.log(a); // Uncaught ReferenceError: a is not defined

闭包是一个可以访问到其他函数内部变量的函数,闭包的重点在于,变量的作用域,和,变量的生命周期。

变量的作用域

// 变量的作用域
var my = function() {
var a = 1;
console.log('my', a); // 1
}
my();
console.log(a) // ReferenceError: a is not defined

变量的声明周期

// 变量的生命周期
let fu = function() {
let a = 0;
a ;
console.log('dada', a);
}
fu(); // 1
fu(); // 1
fu(); // 1 let func = function() {
let a = 0;
return function() {
a ;
console.log('a', a);
}
} let fun = func() fun(); // 1
fun(); // 2
fun(); // 3

闭包中的变量没有被销毁,这个涉及到垃圾回收机制,即标记清楚和引用计数

function num() {
for(var i=0; i< 10; i ) {
setTimeout(function() {
console.log('da', i) // 10
},0)
}
}
num(); function num1() {
for(var i=0; i< 10; i ) {
(function (i) {
setTimeout(function() {
console.log('da', i)
},0)
})(i) // 1,2,3,...,10
}
}
num1()

什么是闭包的例子:

function da() {
var a = 1;
function dada() {
console.log(a);
}
return dada
} var d = da();
d(); // 1

闭包如果不是那么必要,请不要去创建它,因闭包在处理速度和内存消耗方面对性能具有负面影响。

闭包的形式与变量的作用域以及变量的生存周期有着密切的相关性。

变量的作用域:

变量的作用域指的是变量的有效范围,当一个函数中声明的一个变量不带上关键字var的时候,这个变量就成为了全局变量,当这个变量用var声明的时候,这个变量就变成了局部变量,只有在函数内部才能访问到这个变量,在函数外面是访问不到的。举例:

var func = function() {
var a = 1;
alert(a); // 1
};
func();
alert(a); // Uncaught ReferenceError: a is not defined

嵌套例子:

var a = 1;
var fun = function() {
var b = 2;
var func1 = function() {
var c = 3;
alert(b); // 2
alert(a); // 1
}
func1();
alert(c); // c is not defined
};
fun();

变量的生命周期:

闭包的又一重要概念,变量的生命周期,对于全局变量的生命周期来说是永久的,对于函数内部的局部变量来说,是短暂的,它们都会随着调用的结束而被销毁。

var func = function() {
var a = 1;
};
func();
var func = function() {
var a = 1;
return function() {
a ;
alert(a);
}
};
var da = func();
da(); // 2
da(); // 3
da(); // 4

闭包

函数作为返回值

function num(arr) {
return arr.reduce(function (x,y) {
return x y;
});
}
num([1,2,3]); // 6

变成函数

function func(arr) {
var sum = function() {
return arr.reduce(function(x,y) {
return x y;
});
}
return sum;
} // 调用 函数
var da = func([1,2,3]); // 调用函数 // 运行
da(); // 6
var da1 = func([1,2]);
var da2 = func([1,2]);
da1 == da2 // false

每次调用返回的都是一个新的函数

利用闭包进行缓存:

function add(a) {
return a 1;
}

利用闭包进行缓存:

闭包的作用

封装变量,闭包可以封装形成私有变量:

var da = function() {
var a = 1;
for (var i=0; i < arguments.length; i ){
a = a * arguments[i];
}
return a;
}
alert(a(1,2,3));

在JavaScript中是没有块级作用域的概念的:

function add() {
var arr = [ 1,2,3 ];
for (var i=0; i < arr.length; i ) {
alert( arr[i]);
}
var i; // 重新声明变量
alert(i);
}

块级作用域效果,闭包:

(function() {
// 块级作用域
})()

延续局部变量的生命周期:

var myImg = function( src ) {
var img = new Image(0;
img.src = src;
};
myImg('http:///...');

解决请求丢失问题:

var da = (function() {
var imgs = [];
return function(src) {
var img = new Image();
imgs.push(img);
img.src = src;
}
})();

闭包是指有权访问另一个函数作用域中变量的函数。

闭包:函数对象可以通过作用域关联起来,函数体内的变量都可以保存在函数作用域内。

词法作用域:作用域是在编写代码的时候确定的动态作用域:作用域是在代码运行的时候确定的

<script>
function add(num){
var sum = 5;
return sum num;
}
var sum = add(4);
</script>
Execution Contexts = {
variable object:变量对象;
this value: this指针;
scope chain:作用域链;
}

全局变量

function myFunction() {
var a = 4;
return a * a;
}
var a = 4;
function myFunction() {
return a * a;
}
var counter = 0;

function add() {
return counter = 1;
} add();
add();
add(); // 计数器现在为 3
function add() {
var counter = 0;
return counter = 1;
} add();
add();
add(); // 本意是想输出 3, 但事与愿违,输出的都是 1 !
function outter(){
var sky="blue";
function inner(){
console.log(sky);
}
return inner;
} var result=outter();
result(); //"blue"

函数与对其状态即为词法环境的引用共同构成闭包,也就是,闭包可以让你从内部函数访问外部函数作用域。

词法作用域:

function init() {
var name = "dada";
// name 是一个被 init 创建的局部变量
function displayName() {
// displayName() 是内部函数,一个闭包
alert(name);
// 使用了父函数中声明的变量
}
displayName();
}
init();

闭包:

function mFunc() {
var name = "dada";
function displayName() {
alert(name);
}
return displayName;
} var myFunc = mFunc();
myFunc();

高阶函数

什么是高阶函数,JavaScript中的函数都指向某个变量,既然变量可以指向函数,函数的参数能接收变量,那么一个函数就可以接收另一个函数作为参数,就叫高阶函数。

高级函数:

function add(x, y, f) {
return f(x) f(y);
}

'use strict';

function pow(x) {
return x * x;
} var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow);
// [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
var f = function (x) {
return x * x;
}; var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var result = [];
for (var i=0; i<arr.length; i ) {
result.push(f(arr[i]));
}
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x y;
});
// 25
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x * 10 y;
});
// 13579

在一个数组中,删除偶数,保留奇数:

var arr = [1, 2, 4, 5, 6, 9, 10, 15];
var r = arr.filter(function (x) {
return x % 2 !== 0;
});
r;
// [1, 5, 9, 15]

回调函数

var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
console.log(element);
// 依次打印'A', 'B', 'C'
console.log(index);
// 依次打印0, 1, 2
console.log(self);
// self就是变量arr
return true;
});
'use strict';

var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
});
console.log(arr);
// [1, 2, 10, 20]
var a1 = ['B', 'A', 'C'];
var a2 = a1.sort();
a1;
// ['A', 'B', 'C']
a2;
// ['A', 'B', 'C'] a1 === a2;
// true, a1和a2是同一对象

every()方法可以判断数组的所有元素是否满足测试条件

find()方法用于查找符合条件的第一个元素

findIndex()方法返回这个元素的索引

高阶函数即为输入参数里有函数,或是输出是函数的函数

function add() {
var num = 0
return function(a) {
return num = num a
}
}
var adder = add() adder(1)
// 输出: 1
adder(2)
// 输出: 3

高阶函数满足条件:函数作为参数被传递,函数作为返回值输出

回调函数:

var getUserInfo = function( userId, callback ){
$.ajax( 'http://xxx.com/getUserInfo?' userId, function( data ){
if ( typeof callback === 'function' ){
callback( data );
}
});
}
getUserInfo( 522624714, function( data ){
alert ( data.userName );
});
//从小到大排列
[ 1, 5, 3 ].sort( function( a, b ){
return a - b;
});
// 输出: [ 1, 3, 5 ] //从大到小排列
[ 1, 5, 3 ].sort( function( a, b ){
return b - a;
});
// 输出: [ 5, 3, 1 ]

什么是函数式编程,函数式编程时一种编程形式,让你能将函数作为参数传递给其他函数并且能够将函数作为值返回。

在JavaScript中,函数是一类特殊的对象:

function hello() {
console.log('hello');
}
hello();
hello.name='da';

console.log(hello.name); // da
const num = function(x) {
return x*x;
} num(8); // 64

高阶函数是一个函数,它是接收函数作为参数或者是将函数作为输出的值进行返回。高阶函数实战:

const arr1 = [1,2,3];
const arr2 = arr1.map(function(x) {
return x * 2;
});
console.log(arr2);
const arr1 = [1,2,3];
const arr2 = arr1.map(x => x*2);

结语

简而言之,高阶函数是一个函数,它是可以接受函数作为参数,还可以作为返回一个值返回,返回一个函数。闭包可以让你从内部函数访问外部函数作用域。闭包即是一个函数,能够访问另一个函数作用域的变量的函数。

关于目前文章内容即涉及前端,PHP知识点,如果有兴趣即可关注,很荣幸,能被您发现,真是慧眼识英!也感谢您的关注,在未来的日子里,希望能够一直默默的支持我,我也会努力写出更多优秀的作品。我们一起成长,从零基础学编程,将 Web前端领域、数据结构与算法、网络原理等通俗易懂的呈现给小伙伴。分享 Web 前端相关的技术文章、工具资源、精选课程、热点资讯。

推荐阅读

1、你知道多少this,new,bind,call,apply?那我告诉你

2、为什么学习JavaScript设计模式,因为它是核心

意见反馈:若本号内容有做得不到位的地方(比如:涉及版权或其他问题),请及时联系我们进行整改即可,会在第一时间进行处理。

感谢阅读,原创不易,喜欢就点个赞吧,这是我写作最大的动力。

欢迎关注达达的简书!

这是一个有质量,有态度的博客

一篇文章把你带入到JavaScript中的闭包与高级函数的更多相关文章

  1. JavaScript中的闭包与匿名函数

    知识内容: 1.预备知识 - 函数表达式 2.匿名函数 3.闭包 一.函数表达式 1.定义函数的两种方式 函数声明: 1 function func(arg0, arg1, arg2){ 2 // 函 ...

  2. JavaScript中的闭包和匿名函数

    JavaScript中的匿名函数及函数的闭包   1.匿名函数 2.闭包 3.举例 4.注意 1.匿名函数 函数是JavaScript中最灵活的一种对象,这里只是讲解其匿名函数的用途.匿名函数:就是没 ...

  3. 让你分分钟学会Javascript中的闭包

    Javascript中的闭包 前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它 ...

  4. Javascript中的闭包(转载)

    前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...

  5. 狗日的Javascript中的闭包

    前面的话: 闭包,是 javascript 中重要的一个概念,对于初学者来讲,闭包是一个特别抽象的概念,特别是ECMA规范给的定义,如果没有实战经验,你很难从定义去理解它.下面是作者从作用域链慢慢讲到 ...

  6. 难道这就是JavaScript中的"闭包"

    其实对于JavaScript中的"闭包"还没真正理解,这次在实际Coding中似乎遇到了"闭包"的问题,仅此摘录,以待深究. 表现为jQuery的post方法回 ...

  7. JavaScript中常见的数组操作函数及用法

    JavaScript中常见的数组操作函数及用法 昨天写了个帖子,汇总了下常见的JavaScript中的字符串操作函数及用法.今天正好有时间,也去把JavaScript中常见的数组操作函数及用法总结一下 ...

  8. JavaScript中常见的字符串操作函数及用法

    JavaScript中常见的字符串操作函数及用法 最近几次参加前端实习生招聘的笔试,发现很多笔试题都会考到字符串的处理,比方说去哪儿网笔试题.淘宝的笔试题等.如果你经常参加笔试或者也是一个过来人,相信 ...

  9. 浅谈JavaScript中的闭包

    浅谈JavaScript中的闭包 在JavaScript中,闭包是指这样一个函数:它有权访问另一个函数作用域中的变量. 创建一个闭包的常用的方式:在一个函数内部创建另一个函数. 比如: functio ...

随机推荐

  1. 46、VUE + JS 面试宝典

    https://github.com/rohan-paul/Awesome-JavaScript-Interviewshttps://github.com/nieyafei/front-end-int ...

  2. jquery问题,如何调用带this的函数?

    这样写: 1 2 3 4 5 6 7 8 9 10 11 12 $(".aa").on("mouseout",function(){     var obj = ...

  3. QT Graphics-View图元组使用

    通过把一个item作为另一个item的孩子,你可以得到item组的大多数本质特性:这些items会一起移动,所有变换会从父到子传递.QGraphicsItem也可以为它的孩子处理所有的事件,这样就允许 ...

  4. Android Handler类 发送消息-post()和postDelay(), Looper讲解

    https://blog.csdn.net/weixin_41101173/article/details/79701832 首先,post和postDelay都是Handler的方法,用以在子线程中 ...

  5. FFMPEG SDK 开发介绍(原创)

    来源:http://blog.sina.com.cn/s/blog_62a8419a01016exv.html 本文是作者在使用ffmpeg sdk开发过程中的实际经验,现在与大家分享,欢迎学习交流. ...

  6. scala快速入门之文档注释

    scala快速入门之文档注释 1.在项目栏的目录树中找到该源码,右击点击Show in Explorer, 即可找到该源码的本地路径,在路径中输入cmd 2.执行scaladoc -d  生成文档注释 ...

  7. 微信小程序 子组件调用父组件方法

    原文连接   --->  https://blog.csdn.net/qq_40190624/article/details/87972265 组件 js:  var value = 123; ...

  8. Java的常见术语(PO/POJO/VO/BO/DAO/DTO)

    PO(persistant object) 持久对象在o/r 映射的时候出现的概念,如果没有o/r映射,就没有这个概念存在了.通常对应数据模型(数据库),本身还有部分业务逻辑的处理.可以看成是与数据库 ...

  9. Win10 Microsoft Store 微软商店 Error 0x00000193 解决方法

    0x00 前言 最近使用 CFW 过程中使用 Fiddle Web Debug 设置 Store 的回环代理的过程中发现无论是否使用代理,Store 都无法访问网络的问题,在最下面的提示中出现了 0x ...

  10. Beta冲刺第4次

    二.Scrum部分 1. 各成员情况 翟仕佶 学号:201731103226 今日进展 今天不再使用Excel绘制燃尽图,改学习使用highcharts绘制 存在问题 对前端不够了解,第一次在这博客园 ...