前面我们介绍了函数函数式编程,今天我们见到那介绍一下js的函数基础
1.ES
这里简单说一下ES,我们知道ECMAScript是JS的规范,我们常说的ES5,ES6说的就是ECMAScript的版本.ES5就是ECMAScript5,是ECMAScript第五次修订版本,这是现在基本上所有的浏览器都兼容的版本,而且引入了严格模式,而es6是我们现在写代码常用的版本,他是2015年发布的修订,我们也称为ES2015,像后续ES7,ES8之类的我们基本通常也会说ES6。就是一种新旧说法的问题,我们常将ES5之前的叫ES5,ES6之后的叫ES6,如果非要分的那么细的话,也没有太大的必要。比如说我们ES6新增的let、const解构啊,箭头函数...es7新增的includes...es8新增的object.values...es9新增的promise.finally...(这些太多了,以后时间可以新开一章慢慢说)我们在平常将这写新增的方法都叫做es6新增语法。
由于现在并不是每个浏览器都支持ES6,我们要用到Babel,这是一个转换编译器,它可以将现在的最新版的代码,转换成ES5的版本,所以我们现在才可以随意的使用ES6的新特性。
2.创建函数并执行
2.1一个简单函数
()=>{ "fn"}
这就是一个简单的函数,当然他是匿名函数,后面介绍高阶函数的时候再详细介绍。
2.2一个简单有名字的函数
const fn1 = () => 'aaa'
打印台会打印出'aaa',如果我们用babel将他转换一下会得到
“use strict”
var fn1=fuction fn1(){
return 'aaa'
}
2.3严格模式
上面我们看到转换后有个“use strict”上面我们介绍es的时候就说过es5引入了严格模式,严格模式就是js的一种受限变体。运行在严格模式下和非严格模式下的代码,语义上是不同的,所有的没有家“use strict”的代码片段都将进入非严格模式。在严格模式下是由很多优势的,比如我们定义全局变量的时候,我们直接a="b",这在非严格模式下是不会报错,要知道全局的变量在js里面是非常不好的。
这里说一下,我们将“use strict”放在最开头的位置,那么就会在这个整个特定的文件下,开启严格模式,当然你也可以指在特定的函数内部使用,那么他就只作用于那个特定的函数。
2.4 return语句
我们之前发现转译后的代码在我们的基础上面return 'aaa',我们是没有写的。其实如果且只有一段语句得函数,我们可以省略return,因为它默认就返回整个语句。
2.5 多语句函数
如果我们将之前得函数换成
const fn1=()=>{
let a='aaa'
return a
}
我们发现转译返回的结果一样的。但是我们这里就是用了多语句来完成得。我们正好在这里介绍一下var,let,const得区别:
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问,在函数内定义变量时省略var操作符,可以创建一个全家变量就像之前我们说的全局变量a='b'一样,这样很不好。var还会声明提升,var在js中是支持预解析的,因为使用var声明的变量会自动提升到函数作用域顶部,在代码预编译时,javaScript引擎会自动将所有代码里面得var关键字声明的语句都会提升到当前作用域的顶端。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问,let也不允许同一个块作用域中出现冗余声明(重复声明)var可以重复声明(非常不好),let声明的变量不会在作用域中被提升,let申明得变量会产生块级作用域。与var关键字不同,var定义的全局变量会挂载到window对象上,使用window可以访问,而let在全局作用域中声明的变量不会成为window对象的属性。
const的行为与let基本相同,唯一一个重要的区别是,const是用来定义常量的,而且定义的时候必须赋值,不赋值会报错,定义之后是不允许被修改的,修改const声明的变量会导致运行时错误。但是这里我们定义对象,修改队形内部得数据并不会报错,因为复杂数据类型在栈区保存的是对象在堆区的地址,修改对象的属性,不会修改对象在栈区的地址。
我们简单来个函数意思一下:
const fn1 = () => {
// 函数作用域
if (true) {
let a = 1
var b = 2
console.log(a)
console.log(b)
} // if块作用域
console.log(b) // 函数作用域
console.log(a) // 函数作用域
}
fn1()
我们运行一下
从输出中可以看出,用 let 关键字声明的变量只在if在块内可访问。当我们在块外访问变量a的时候,js抛出了异常ReferenceError(如果变量在当前作用域中被创建出来,由于此时还未完成语法绑定,所以是不能被访问的,如果访问就会抛出错误ReferenceError。因此,在这运行流程进入作用域创建变量,到变量可以被访问之间的这一段时间,就称之为暂时死区。);但是对于用 var 声明的变量,并非如此。它将变量作用域声明为整个函数。这就是变量b在if块外可被访问的原因。
2.7 函数参数
刚才扯远了,我们说一下函数参数,这个es5,es6没什么变化。没什么好说的。说一下,ES5的函数在ES6或者更高版本其实还是有效的。只是我们现在用多了会发现,新版的简单方便好用。对编写代码的人来说,方便了许多,代码阅读体验也会好不少。
3.创建项目
3.1初始化
我们直接创建一个文件夹放我们的代码
然后npm init 就会出现一堆问题,然后看自己怎么填,不想填就一直回车到yes,完成以后会出现package.json文件。
我们现在添加一些允许编写并执行代码的类库。
npm i --save-dev babel-preset-es2017-node7 版本的话,自己自由安装就可以了。安装这个主要是为了代码可以在nodejs平台上运行。因为我们使用的--save-dev,npm就会把babel的相应依赖加到package.json里面,我们现在打开package.json
(这里还需要装一个babel-cli)
我们在创一个lib和working文件夹,lib里面放相关的函数式类代码库的代码,working里面去运行和理解函数式技术。
3.2用函数式方法处理循环问题
我们在lib里面创个文件fuctional.js,写入代码
const forEach = (array, fn) => {
for (let i = 0; i < array.length; i++) {
fn(array[i])
}
}
export default forEach
再在working里面创建play.js
import forEach from '../lib/fuctional'
const array = [1, 2, 3]
forEach(array, item => console.log(item)) //使用导入的forEach
babel-node working/play.js --presets es2017在babel-node运行以后的到123
这里如果发现(babel : 无法将“babel”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写,如果包括路径,请确保路径正确,然后再试一次。这种错误,一般是环境变量的问题,babel -v确定没读取到,npm config get prefix看一下路径,手动添加到系统环境变量)
3.3在npm中创建脚本
上面的这种太麻烦,每次都输这么长一大串
我们直接在package.json里面scripts里面添加启动命令就行
这样以后我们只需要npm run start就可以了。
3.4git仓库
这个看你自己用的什么,创一个记好了,国内的话,没科学上网的手段就用码云就行了。
这一章可能有点乱有点杂,不过都是些基础的东西。看看意思一下就好,下一章我们说一说高阶函数。