补充知识:Symbols类型
ES6提供了Symbol类型,内建原生类型
// symbol
let s = Symbol()
console.log(s)
let s1 = Symbol()
console.log(s1)
console.log(s == s1) // false,Synbol每次定义取的值都是不同的
let a = 1
let obj = {
a, // a是变量
b: 'abc', // b不是变量,是key
//s:s // 前面的s是key,不是变量,后面的s是变量
// s // s是变量
[s]: 2000 // s是变量
}
console.log(obj)
// { a: 1, b: 'abc', [Symbol()]: 2000 }
for(let x in obj){
console.log(x) // 注意 [Symbol()]: 2000是访问不到的
// a b
}
var color_obj = {
red: 'rec',
blue: 'blue',
black: 'black',
green: 'green'
}
const color = {
red: Symbol(),
blue: Symbol(),
black: Symbol(),
white: Symbol()
}
function 函数名(参数列表){
函数体;
return 返回值;
}
function add(x, y){
return x + y;
}
console.log(add(4, 5)) // 9
使用表达式来定义函数,表达式中的函数名可以省略,如果这个函数名不省略,也只能用在此内部。
// 匿名函数
const add = function(x, y){
return x + y
}
console.log(add(4, 5)) // 9
// 有名字的函数表达式
const sub = function fn(x, y){ // fn只能在此内部使用
return x - y
}
console.log(fn(5, 1)) // 会报错,fn只能在定义的函数内部使用,就是说递归的时候使用
// 有名字的函数表达式,实现递归求和
const sum = function _sum(n){
if (n == 1){
return 1
}
return n + _sum(n - 1) // n + _sum(--n) 也可以,但是不能写成_sum(--n) + n
}
console.log(sum(5)) // 15
函数、匿名函数、函数表达式的差异
函数和匿名函数本质是一样的,都是函数对象,只不过函数有自己的标识符——函数名,匿名函数需要借助其他标识符而已,而函数与函数表达式的区别在于,函数有声明提升,而函数表达式没有。
console.log(add(4, 6)) // 直接输出结果10
function add(x, y){ // 声明提升
return x + y
}
console.log(sub(10, 1)) // 会报错,函数表达式没有声明提升
const sub = function(x, y){
return x - y
}
高阶函数是函数作为其参数或者返回值为参数的函数。
完成一个计数器函数counter:
const counter = function(){
let c = 0
return function(){
return ++c
}
}
const c = counter() // 返回一个函数对象
console.log(c())
console.log(c())
console.log(c())
console.log(c())
console.log(c())
完成map函数,实现对某一个数组的元素进行某种处理(如使数组中的每一个元素都加1),返回新的数组
const add = function(c){
return c + 1
}
const map = function(arr, func){
let new_arr = []
for(let i = 0; i < arr.length; i++){
new_arr[i] = func(arr[i])
}
return new_arr
}
console.log(map([1, 2, 3, 4], add))
// [ 2, 3, 4, 5 ]
箭头函数就是匿名函数,它是一种更加精简的格式。
箭头函数参数
箭头函数返回值:
const add = function(c){
return c + 1
}
const map = function(arr, func){
let new_arr = []
for(let i = 0; i < arr.length; i++){
new_arr[i] = func(arr[i])
}
return new_arr
}
console.log(map([1, 2, 3, 4], y => console.log(y)))
/*
1
2
3
4
[ undefined, undefined, undefined, undefined ]
*/
console.log(map([1, 2, 3, 4], y => {y}))
// [ undefined, undefined, undefined, undefined ]
一个参数占一个位置,支持默认参数
const add = (x, y) => x + y
console.log(add(4, 5))
const sub = (x, y=5) => x - y
console.log(sub(9, 3)) // 6
console.log(sub(10)) // 5
const add2 = (x=10, y) => x + y
console.log(add()) // NaN
console.log(add(1)) // NaN
console.log(add(y=2, z=3)) // 5
// JS中没有关键字传参,只是做参数位置的对应,并不限制默认参数的位置,传的是赋值表达式的值
建议:默认参数写到后面,这是一个好习惯
JS中使用...表示 可变参数,(python使用*收集多个参数)
const sum = function(...args){
let result = 0
console.log(args) // [ 3, 6, 9, 12 ]
// args是数组,要解构的话使用...args
for(let x in args){
result += args[x]
}
return result
}
console.log(sum(3, 6, 9, 12)) // 30
arguments对象:
function fn(p, ...args){
console.log(p)
console.log(args)
console.log('~~~~~~~~~~~~~~')
console.log(arguments) // 对象
for(let x of arguments){ // 该对象可以使用of
console.log(x)
}
}
fn('abc', 1, 3, 4)
/*
abc
[ 1, 3, 4 ]
~~~~~~~~~~~~~~
[Arguments] { '0': 'abc', '1': 1, '2': 3, '3': 4 }
abc
1
3
4
*/
ES6之前,arguments是唯一可变参数的实现。ES6开始,不推荐,建议使用可变参数,为了兼容而保留。注意,使用箭头函数,取到的arguments不是我们想要的。
const f = (x, ...args) => {
console.log(args) // [ 2, 3, 4 ]
console.log(x) // 1
console.log(arguments) // 不是传入的值
}
f(...[1, 2, 3, 4])
参数解构:
和python类似,JS提供了 参数解构,依然使用..符号来解构。
const add = (x, y) => {console.log(x, y); return x + y}
console.log(add(...[10, 20]))
console.log(add(...[1, 2, 3, 4, 5])) // 3
console.log(add(...[100])) // NaN
JS支持参数解构,不需要解构后的值个数和参数个数对应。
python中可以使用,return 1, 2返回多个值,本质上就是一个值,就是一个元组。
const add = (x, y) => {return x, y} //返回的是逗号表达式的值
console.log(add(4, 5)) // 5
表达式的值:类C的语言,都有一个概念--表达式的值;赋值表达式的值:等号右边的值;逗号表达式的值:就是最后一个表达式的值。JS的函数返回值依然是单值。严格模式:使用"use strict",这条语句放到函数的首行,或者js脚本的首行。
JS的异常语法与java相同,使用throw关键字抛出。使用throw关键字可以抛出任意对象的异常。
throw new Error('new error');
throw new ReferenceError('Ref Error');
throw 1;
throw 'not ok'
throw [1, 2, 3]
throw {'a': 1};
throw () => {}; // 函数
try...catch语句捕获异常,finally保证最终一定执行。注意这里的catch不支持类型,也就是说至多一个catch语句,可以在catch语句块内,自行处理异常。
try{
throw new Error('new error')
// throw new ReferenceError('Ref Error')
}catch(error){
console.log(error)
console.log(typeof error) // object
console.log(error.constructor.name) // Error
}finally{
console.log('===========end===============')
}