JavaScript学习过程中的个人笔记,详细请看https://www.liaoxuefeng.com/wiki/1022910821149312 再次感谢廖大
函数的定义
function abs ( x) {
return x;
}
var abs = function ( x) {
return x;
} ;
Js允许传入任意个参数而不影响调用。 Js有一个关键字arguments,它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。类似一个Array但不是。 通过arguments,即使函数不定义任何参数,还是可以拿到参数的值。 实际上arguments最常用于判断传入参数的个数。 ES6引入了rest参数,用来获取除定义外的其他参数。
function foo ( a, b, ... rest) { }
变量
Js的函数中会先扫描整个函数体的语句,把所有声明的变量提升到函数顶部,但不会提升变量的赋值。
'use strict'
var x = 'Hello, ' + y;
console. log ( x) ;
var y = 'Bob' ;
不在任何函数内定义的变量就具有全局作用域。实际上Js默认有一个全局对象window。全局作用域的变量实际上被绑定到window的一个属性。
名称空间
全局变量会绑定到window上,不同的Js文件如果使用了相同的全局变量,或者定义了相同名字的顶层函数,都会造成命名冲突,并且很难被发现。 减少冲突的一个方法是把自己的所有变量和函数全部绑定到一个全局变量中。
var MYAPP = { } ;
MYAPP . name = 'myapp' ;
MYAPP . version = 1.0 ;
MYAPP . foo = function ( ) { return 'foo' } ;
局部作用域
Js的变量作用域实际上是函数内部,我们在for循环等语句块中是无法定义具有局部作用域的变量的。 ES6引入了关键字let,用let代替var可以什么一个块级作用域的变量。
常量
要声明一个常量,在ES6前是不行的,我们通常用全部大写的变量来表示这是一个常量,不要修改它的值。 ES6引入了关键字const来定义常量,const和let都具有块级作用域。
解构赋值
ES6开始,JS引入了解构赋值,可以同时对一组变量进行赋值。
'use strict' ;
var [ x, y, z] = [ 'hello' , 'JavaScript' , 'ES6' ] ;
let [ x, [ y, z] ] = [ 'hello' , [ 'JavaScript' , 'ES6' ] ] ;
var [ , , z] = [ 'hello' , 'JavaScript' , 'ES6' ] ;
var person = {
name: '小明' ,
age: 20 ,
gender: 'male' ,
passport: 'G-1234567' ,
school: 'No.4 middle school' ,
address: {
city: 'beijing' ,
zipcode: '10001 ;
}
} ;
var { name, age, passport, address: { city, zipcode} } = person;
let { name, passport: id} = person;
var { name, single = true } = person;
如果一个函数接受一个对象作为参数,那么可以使用解构直接把对象的属性绑定到变量中。
方法
在一个对象中绑定函数,称为这个对象的方法。 在一个方法内部,this始终指向当前对象。 Js的函数内部如果调用了this,那么这个this的指向视情况而定: 1)如果以对象的方法形式调用,该函数的this指向被调用的对象 2)如果单独调用函数,此时,此函数的this指向全局对象,也就是window。 可以用函数本身的apply方法来指定函数的this指向哪个对象,它接收两个参数,第一个参数是需要绑定的this变量,第二个参数是Array,表示函数本身的参数。 还可以使用call方法,和apply的区别是,apply()把参数打包成Array传入,call()把参数按顺序传入。
高阶函数
Js的函数都指向某个变量。一个函数也可以接收另一个函数作为参数,这种函数就称之为高阶函数。 Array().map():创建一个新数组,其结果是该数组中的每个元素是调用一次提供的函数后的返回值。 Array().reduce():这个函数必须接收两个参数,reduce()把结果继续和序列的下一个元素做累积计算。 Array().filter():接收一个函数,将传入的函数依次作用于每个元素,然后根据返回值是true或false来决定保留或丢弃该元素。 Array().sort():排序方法,可以传入一个方法来进行自定义排序,默认的排序方法是暗示ASCII码排序,并不精确。 Array().every():判断数组的所有元素是否满足测试条件。 Array().find():用于查找符合条件的第一个元素,如果找到了返回这个元素,否则,返回undefined。 Array().findIndex():用于查找符合条件的第一个元素,如果找到了返回这个元素的索引,否则,返回-1; Array().forEach():与map类似,把每个元素依次作用于传入的函数,但不会返回行的数组。常用于遍历数组,因此传入的函数不需要返回值。
闭包
高阶函数出了可以接受函数作为参数外,还可以把函数作为结果值返回。 返回函数不要引用任何循环变量,或者后续会发生变化的变量。 如果一定要引用循环变量,可以再创建一个函数,用该函数的参数绑定循环变量当前的值,无论该循环变量后续如何更改,已绑定到函数参数的值不变。 创建一个匿名函数并立即执行的语法:
( function ( x) { return x * x; } ) ( 3 ) ;
借助闭包,可以用来封装私有变量。闭包就是携带状态的函数,并且它的状态可以完全对外隐藏起来。
箭头函数
ES6标准新增了一种新的函数:Arrow Function(箭头函数)。 箭头函数相当于匿名函数,并且简化了函数定义。 箭头函数有两种格式:
x => x * x;
x => {
if ( x > 0 ) {
return x * x;
}
else {
return - x* x;
}
}
( x, y) => x * x + y * y;
( ) => 3.14 ;
( x, y, ... rest) => {
var i, sum = x + y;
for ( i = 0 ; i< rest. length; i++ ) {
sum += rest[ i] ;
}
return sum;
}
x => ( { foo: x } )
箭头函数和匿名函数有个明显的区别:箭头函数修复了this的指向,箭头函数内部的 this 是词法作用域,由上下文确定。 由于this在箭头函数中已经按照词法作用域绑定了,所以用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略。
generator(生成器)
generator是ES6引入的新的数据类型,一个generator看上去像一个函数,但可以返回多次。 generator由function *定义,并且除了return语句,还可以用yield返回多次。 调用generator对象有两种方法, 1)不断调用generator对象的next()方法,这个方法每次遇到yield x 就会返回一个对象{value:x,done:true/false},然后暂停,返回的value就是yield的返回值,done表示这个generator是否已经执行结束了,如果done为true,则value就是return的返回值。 2)直接用for…of循环迭代generator的对象,这种方式就不需要自己判断done。