We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
初阶部分 字符串可以保存为变量,函数说他也可以
var wscats = 'wscats'; var wscats_fn = function () { return 'wscats'; };
字符串可以保存对象字段,函数说他也可以
var wscats = { wscats: 'wscats', wscats_fn: function () { return 'wscats' } };
字符串可以用时再创建,函数说他也可以
'Ws' + (function() { return 'Cat' })();
字符串可以作为参数传给函数,函数说他也可以
var wscats; function wscats_fn() {}; function hellloWorld(wscats, wscats_fn) { return; }
字符串可以作为函数返回值,函数说他也可以
return 'wscats'; return function () { return 'wscats'; };
所以函数真的是JS里面的上等好公民啊可以穿梭于任何地方,并谈笑风生 高阶部分: 有了上面的例子,那么我们就可以把函数这个小孩子带到好多好玩的地方,往下慢慢看~ 首先看第一个例子
var obj1 = { value: 'eno' }, obj2 = { value: 'wscats' }, obj3 = { value: 'yao' }; var values = []; function add(obj) { values.push(obj.value); } add(obj1); add(obj2); console.log(values); // eno,wscats
这种写法,大家都知道了,变量会污染全局环境,并且一旦有一个地方忘记修改了就会变得很不稳定,不像函数体一样,只负责内部的输入输出,这里如果融入上下文的其他函数和变量就会变得非常混乱
根据这样修改成第二个例子:
var obj1 = { value: 'eno' }, obj2 = { value: 'wscats' }, obj3 = { value: 'yao' }; function add(obj) { var values = []; values.push(obj.value); return values; } 跟下面一样 /*function add(obj) { var values = []; var accumulate = function() { values.push(obj.value); }; accumulate(); return values; }*/ add(obj1); add(obj2); console.log(add(obj1)); // eno console.log(add(obj2)); // wscats
这样我们把values数组声明放进去函数内部,这样就不会被其他外部变量骚扰了,但是问题又来了,只有最后传入对象值才可以返回,那不是我们的初衷
最后看消除所有尴尬的第三个例子:
var obj1 = { value: 'eno' }, obj2 = { value: 'wscats' }, obj3 = { value: 'yao' }; var Add = function (obj) { var values = []; var _calc = function (obj) { if (obj) { values.push(obj.value); return values; } else { return values; } }; return _calc; //可以这样把它看成匿名函数省去一个没必要的变量 /*return function(obj) { if (obj) { values.push(obj.value); return values; } else { return values; } }*/ }; var calc = Add(); calc(obj1); //相当于ValueAccumulator()(obj1) calc(obj2); //走if分支 console.log(calc()); //走else的分支
这里制造一个闭包来保存第一层函数的values数组,这个数组既可以被内部函数_calc调用,也可以在自己函数体内调用;第一层函数的关键点在于返回的是在自己内部定义的那个函数_calc,这个hack就能让Add函数在外部能访问函数体内的一直保存的values数组,进一步说这种方法可以得到第一层函数任何一个声明的变量,这是闭包的一个很常见的用法(返回函数)。
理解下面这些话
JS中的闭包就是函数可以访问父作用域(这个总结够短的,有争议的可以先搁置争议) 上面其实可以看做是自执行的匿名函数(_calc可以它看成一个匿名函数输出来),自执行的函数实际上是高阶函数的一种形式。高阶函数就是以其它函数为输入,或者返回一个函数为输出的函数(这个理解越来越像是闭包的理解了) 所以函数将其他函数作为输入参数或者作为返回值,就可以称为高阶函数
JS中的闭包就是函数可以访问父作用域(这个总结够短的,有争议的可以先搁置争议)
上面其实可以看做是自执行的匿名函数(_calc可以它看成一个匿名函数输出来),自执行的函数实际上是高阶函数的一种形式。高阶函数就是以其它函数为输入,或者返回一个函数为输出的函数(这个理解越来越像是闭包的理解了)
所以函数将其他函数作为输入参数或者作为返回值,就可以称为高阶函数
上面其实还需要了解一个知识点就是纯函数
//非纯函数 var wscats1 = function(str) { window.innerHeight; window.innerWidth; return str + 's innerHeight: ' + window.innerWidth + 'px'; }; //纯函数 var wscats2 = function(str, height) { return str + 's innerHeight: ' + height + 'px'; }; console.log(wscats1('wscats')); console.log(wscats2('wscats', 254));
两个函数的区别在于非纯函数依赖window这个全局对象的状态来计算宽度和高度,而自给自足的纯函数则要求这些值作为参数传入,当一个函数是纯的,也就是不依赖于当前状态和环境,我们就不用管它实际的计算结果是什么时候被计算出来。
纯函数返回的计算结果仅与传入的参数相关 纯函数是完完全全独立的,所以它适合被重复调用使用,为下面的函数编程做一个好铺垫
纯函数返回的计算结果仅与传入的参数相关
纯函数是完完全全独立的,所以它适合被重复调用使用,为下面的函数编程做一个好铺垫
有更深刻理解或者有误的话请务必提醒并留言我~
回到题目核心的JS函数编程 由于JS中,函数是头等公民,这里的实际意思就是函数被认定最基本最根本的类型,正如数字和对象一样。 如果数字和对象可以被来回传递,那么函数(函数我为什么就不可以呢)也可以的。 这就是JS函数编程的基本思想吧
那下面第四段代码就是在第三段代码后面的基础上再添加,实现这种思路
var calc2 = Add(); var objects = [obj1, obj2, obj3]; // 这个数组可以很大 objects.forEach(calc2); //注意对象foeEach的用法 array.forEach(callbackfn[, thisArg]);对于数组中的每个元素,forEach都会调用callbackfn函数一次 console.log(calc2());
这里的calc2函数就变成一个‘变量’进入到forEach参数内
我们可以在这个基础上继续扩充功能,第五段代码,链式调用
objects1 = objects.reverse(); objects2 = objects1.concat([4, 16]); objects3 = objects2.map(Math.sqrt); console.log(objects3);
用jQuery用多了,就会知道,jq习惯把类似上面的代码链式调用 类似这样把代码串在一起
console.log(['eno', 'wscats', 'yao'].reverse().concat([4, 16]).map(Math.sqrt)); //NaN,NaN,NaN,2,4 //写明显一点 console.log( ['eno', 'wscats', 'yao'] .reverse() .concat([4, 16]) .map(Math.sqrt) );
这样用的前提必须是这个函数对象里面拥有这个方法,换句话说就是Array.prototype有这个方法(例如reverse, concat ,map) 给他扩充一个简单的方法如下:
Array.prototype.make4 = function() { console.log(this[4]); //this.length=4; return this[4]; } console.log(['eno', 'wscats', 'yao'].reverse().concat([4, 16]).map(Math.sqrt).make4()); //4
上面除了展示匿名函数,链式调用,还有有一种方法是函数式编程里面常用的,就是递归
var Add2 = function(n) { if (n < 0) { // 基准情形 return 'I am wscats'; } else { // 递归情形 return Add2(n - 1); } } console.log(Add2(5));
注意,基准情形就是让递归停止下来的条件,防止无限递归
再复杂点就叫分而治之,其实数学界很多问题都可以用递归解决的
var Add3 = function(a, b) { if (a < 0 && b == 8) { console.log(a % b); //-1 // 基准情形 return 'I am wscats'; } else { // 递归情形 return Add3(a - 1, b); } } console.log(Add3(5, 8)); console.log(Add3(5, 7)); //Maximum call stack size exceeded
The text was updated successfully, but these errors were encountered:
建议给代码排下版
Sorry, something went wrong.
写的很好,建议给代码排下版
No branches or pull requests
初阶部分
字符串可以保存为变量,函数说他也可以
字符串可以保存对象字段,函数说他也可以
字符串可以用时再创建,函数说他也可以
字符串可以作为参数传给函数,函数说他也可以
字符串可以作为函数返回值,函数说他也可以
所以函数真的是JS里面的上等好公民啊
可以穿梭于任何地方,并谈笑风生高阶部分:
有了上面的例子,那么我们就可以把函数这个小孩子带到好多好玩的地方,往下慢慢看~
首先看第一个例子
这种写法,大家都知道了,变量会污染全局环境,并且一旦有一个地方忘记修改了就会变得很不稳定,不像函数体一样,只负责内部的输入输出,这里如果融入上下文的其他函数和变量就会变得非常混乱
根据这样修改成第二个例子:
这样我们把values数组声明放进去函数内部,这样就不会被其他外部变量骚扰了,但是问题又来了,只有最后传入对象值才可以返回,那不是我们的初衷
最后看消除所有尴尬的第三个例子:
这里制造一个闭包来保存第一层函数的values数组,这个数组既可以被内部函数_calc调用,也可以在自己函数体内调用;第一层函数的关键点在于返回的是在自己内部定义的那个函数_calc,这个hack就能让Add函数在外部能访问函数体内的一直保存的values数组,进一步说这种方法可以得到第一层函数任何一个声明的变量,这是闭包的一个很常见的用法(返回函数)。
理解下面这些话
上面其实还需要了解一个知识点就是纯函数
两个函数的区别在于非纯函数依赖window这个全局对象的状态来计算宽度和高度,而自给自足的纯函数则要求这些值作为参数传入,当一个函数是纯的,也就是不依赖于当前状态和环境,我们就不用管它实际的计算结果是什么时候被计算出来。
有更深刻理解或者有误的话请务必提醒并留言我~
回到题目核心的JS函数编程
由于JS中,函数是头等公民,这里的实际意思就是函数被认定最基本最根本的类型,正如数字和对象一样。 如果数字和对象可以被来回传递,那么函数(函数我为什么就不可以呢)也可以的。
这就是JS函数编程的基本思想吧
那下面第四段代码就是在第三段代码后面的基础上再添加,实现这种思路
这里的calc2函数就变成一个‘变量’进入到forEach参数内
我们可以在这个基础上继续扩充功能,第五段代码,链式调用
用jQuery用多了,就会知道,jq习惯把类似上面的代码链式调用
类似这样把代码串在一起
这样用的前提必须是这个函数对象里面拥有这个方法,换句话说就是Array.prototype有这个方法(例如reverse, concat ,map)
给他扩充一个简单的方法如下:
上面除了展示匿名函数,链式调用,还有有一种方法是函数式编程里面常用的,就是递归
注意,基准情形就是让递归停止下来的条件,防止无限递归
再复杂点就叫分而治之,其实数学界很多问题都可以用递归解决的
The text was updated successfully, but these errors were encountered: