其他章节请看:

es6 快速入门 系列

函数

函数是所有编程语言的重要组成部分,es6之前函数语法一直没什么变化,遗留了许多问题,javaScript开发者多年来不断抱怨,es6终于决定大力度更新函数特性,函数变得比以前更易于使用了。

试图解决的问题

默认参数

es5中模拟默认参数,通常这么实现:

function demo1(v1, v2, v3){
v2 = v2 || 11
v3 = v3 || 22
}

更安全的做法是使用 typeof 检查

// 流行的javaScript库中均使用类似的模式
function demo2(v1, v2, v3){
v2 = (typeof v2 !== 'undefined') ? v2 : 11
v3 = (typeof v3 !== 'undefined') ? v3 : 22
}

无命名参数

不容易发现下面的函数 pick 可以接受任意数量的参数

// desc: 取出obj对象中的指定属性
function pick(obj){
const result = {}
for(let i = 1, l = arguments.length; i < l; i++){
result[arguments[i]] = obj[arguments[i]]
}
return result;
}
const obj = {name: 'aaron', age:18, sex: 'man'} // 将obj对象中的name和sex属性取出
// { name: 'aaron', sex: 'man' }
console.log(pick(obj, 'name', 'sex'))

函数创建

创建函数的方式不太简洁,期待能少写一些字符来创建下面的函数

let getValue = function(v){
return v
} let sum = function(v1, v2){
return v1 + v2
} let noop = function(){}

解决方法

默认参数

es6能在形参中指定默认值,就像这样:

function demo2(v1, v2 = 11, v3 = 22){
console.log(v2)
console.log(v3)
}
// 11 22
demo2('v1')
// 11 33
demo2('v1', undefined, 33)
// null 22
demo2('v1', null)

:全等于 undefined 才使用默认值

无命名参数

不定参数:函数的参数前加三个点(...)就表示这是一个不定参数,该参数是一个数组

用不定参数解决上面pick函数的问题:不容易发现pick()可以接受任意数量的参数

// desc: 取出obj对象中的指定属性
function pick(obj, ...keys){
const result = {}
for(let i = 0, l = keys.length; i < l; i++){
result[keys[i]] = obj[keys[i]]
}
return result;
}
const obj = {name: 'aaron', age:18, sex: 'man'} // 将obj对象中的name和sex属性取出
// { name: 'aaron', sex: 'man' }
console.log(pick(obj, 'name', 'sex'))

:不定参数有两条限制

  • 每个函数只能声明一个不定参数,且一定要放在所有参数后面
  • 不定参数不能用于对象字面量 setter 中
// 错误:不定参数不在末尾
function pick(obj, ...keys, last){} // 错误(之所以这么限制,是因为对象字面量 setter 的参数有且只能有一个)
let obj = {
set name(...v){
console.log('hello')
}
}
obj.name = 1;

函数创建

es6提供一种创建函数的新语法,即箭头函数,更加轻量,简介。

箭头函数的语法多变,根据实际场景由多种形式。所有变体都由函数参数、箭头和函数体组成

let getValue = v => v

// 实际上相当于

let getValue = function(v){
return v
}
let sum = (v1, v2) => v1 + v2;

// 实际上相当于

let sum = function(v1, v2){
return v1 + v2
}
let noop = () => {}

// 实际上相当于

let noop = function(){}
let getNumber = () => 100

// 实际上相当于

let getNumber = function(){
return 100
}

如果想通过箭头函数返回一个对象字面量,需要用将对象字面量包裹在括号中

let demo = id => ({id: id, age: 18})

// 实际上相当于

let demo = function(id){
return {id: id, age: 18}
}

箭头函数没有 this,箭头函数的 this 由外围最近一层非箭头函数决定

// 箭头函数的this,就是函数init中的this
let obj = {
id: 11,
init: function(){
document.addEventListener('click', evt => {
console.log(this.id) // 11
})
}
}
obj.init()

箭头函数也没有superargumentsnew.target,这些值与 this 一样,都有外围最近一层非箭头函数决定

不能通过 new 关键字调用,因为头函数没有[[Constructor]],所以不能被用作构造函数

const Sum = (v1, v2) => v1 + v2
new Sum() // 报错

补充

默认参数

默认参数可以传非原始值

function getValue(){
console.log('执行')
return 11
}
/* 通过函数执行来得到参数的默认值 */
function demo2(v1, v2 = getValue()){
console.log(v2)
}
demo2('v1') // 执行 11
demo2('v1', 12)

默认参数的临时死区

function getValue(v){
return v
}
function add(first=getValue(second), second = 100){
const result = first + second
console.log(result)
return result
}
add(1, 2) // 3 {1}
add(undefined, 2) // 报错 {2}
add(10) // 110 {3}

默认参数也存在讲let和const时介绍的临时死区TDZ

// {1}:表示调用add(1, 2)时的js代码
let first = 1
let second = 1; // {2}: 表示调用add(undefined, 2)时的js代码
let first = getValue(second) // second还在临时死区中
let second = 2

增强的Function

Function构造函数,我们通常用它来构造新的函数,这种构造函数接受字符串的形式,分别是函数的参数和函数体

const add = new Function('v1', 'v2', 'return v1 + v2')
console.log(add(10, 20)) // 30

es6中Function构造函数也支持默认参数和不定参数

// 默认参数
const add = new Function('v1', 'v2 = 20', 'return v1 + v2')
console.log(add(10)) // 30 // 不定参数
const add = new Function('...keys', 'return keys[0] + keys[1]')
console.log(add(10, 20)) // 30

展开运算符

展开运算符与函数中的不定参数很相似

console.log(Math.max(1, 3, 2)); // 3

// 展开运算符
console.log(Math.max(...[1, 3, 2])) // 3
console.log(Math.max(...[1, 3, 2], 4)) // 4

不定参数是将各自独立的参数整合成一个数组,展开运算符是将一个数组打散后作为独立的参数传入函数

判断函数是否用new调用

es6中引入 new.target 来解决判断函数是否通过new关键字调用的问题

// es5中限制函数必须通过new调用的实现如下:
function People(){
if(this instanceof People){
console.log('created')
}else{
throw new Error('必须通过 new 调用')
}
} const p1 = new People() // created
People.call(p1) // created(有效)

当调用函数的[[Constructor]]方法时,new.target被赋值为new操作符的目标,如果调用[[Call]]方法,则new.target的值为undefined

function People(){
if(new.target === People){
console.log('created')
}else{
throw new Error('必须通过 new 调用')
}
} const p1 = new People() // created
People.call(p1) // Error: 必须通过 new 调用

:js函数有两个内部方法:[[Call]]和[[Construct]],当通过new关键字调用函数时,执行[[Construct]]函数,它负责创建称作实例的新对象;如果不通过new关键字调用函数,则执行[[Call]]函数,从而直接执行代码中的函数体

其他章节请看:

es6 快速入门 系列

es6 快速入门 —— 函数的更多相关文章

  1. ES6快速入门(一)函数与作用域

    ES6快速入门 一.块级绑定 1.var声明与变量提升 使用var声明的变量,不论在何处都会被视为(声明)在函数级作用域顶部的位置发生. function getValue(condition) { ...

  2. ES6快速入门(二)数据结构

    ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...

  3. python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)

    BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ...

  4. es6 快速入门 系列

    es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...

  5. es6 快速入门 系列 —— 变量声明:let和const

    其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...

  6. es6 快速入门 系列 —— promise

    其他章节请看: es6 快速入门 系列 Promise Promise 是一种异步编程的选择 初步认识Promise 用 Promise 来实现这样一个功能:发送一个 ajax,返回后输出 json ...

  7. es6快速入门 系列 - async

    其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...

  8. es6 快速入门 系列 —— 类 (class)

    其他章节请看: es6 快速入门 系列 类 类(class)是 javascript 新特性的一个重要组成部分,这一特性提供了一种更简洁的语法和更好的功能,可以让你通过一个安全.一致的方式来自定义对象 ...

  9. es6 快速入门 系列 —— 对象

    其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...

随机推荐

  1. Codeforces Round #656 (Div. 3) A. Three Pairwise Maximums

    题目链接:https://codeforces.com/contest/1385/problem/A 题意 给出三个正整数 $x,y,z$,找出三个正整数 $a,b,c$ 使得 $x = max(a, ...

  2. hdu5317 RGCDQ

    Problem Description Mr. Hdu is interested in Greatest Common Divisor (GCD). He wants to find more an ...

  3. 一、Python简介及下载安装

    一.关于Python Python是目前比较受欢迎的脚本语言之一,具有简洁性.易读性以及可扩展性的特点. Python与Java均可以写网页,也可以写后台功能,区别是Python执行效率低,开发效率高 ...

  4. 02、scrapy安装

    1.安装scrapy 采用pip的安装方式,从豆瓣源获取 pip install -i https://pypi.douban.com/simple/ scrapy 安装过程中会报出错误: build ...

  5. 容器技术学习系列(一)-Docker基础知识学习

    一.概述 1.Docker是什么? 1)Docker是世界领先的软件容器化平台 2)Docker公司开发,开源,托管在github 3)跨平台,支持Windows.MacOS.Linux 2.Dock ...

  6. win10安装CUDA CUDNN tensorflow-gpu 1.14

    #1 安装anaconda 官网下载安装即可.python3.7版本 #2 安装CUDA CUDNN   tensorflowgpu1.14 对应CUDNN 7.6.1 CUDA 10.0 注意ten ...

  7. LOJ6285 数列分块入门9(分块 区间众数)题解

    题意:给出区间内的最小众数 思路:分块,离散化每个数,开vector记录每个数p出现的位置,这样就能二分出L,R以内p的个数了.众数有一个性质,用mode(a)表示集合a的众数,那么mode(a∪b) ...

  8. filter_var 函数()绕过执行命令

    escape 过滤器来过滤link,而实际上这里的 escape 过滤器,是用PHP内置函数 htmlspecialchars 来实现的 htmlspecialchars 函数定义如下: htmlsp ...

  9. proto3 协议指引

    一.protocal buffer 是什么? 一种序列化机制. 什么是序列化? 一种转化为可存储和传输对象的过程. 序列化的方式有很多,那么proto有什么特殊的呢? 它的英文介绍里提到了neutra ...

  10. μC/OS-III---I笔记6---互斥信号量

    互斥信号量 操作系统中利用信号量解决进程间的同步和互斥(互斥信号量)的问题,在多道程序环境下,操作系统就是遮掩实现进程之间的同步和互斥.但是在使用的过程中厉害的前辈还是发现了这一优秀机制的缺陷,它会导 ...