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()
箭头函数也没有super、arguments、new.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快速入门(一)函数与作用域
ES6快速入门 一.块级绑定 1.var声明与变量提升 使用var声明的变量,不论在何处都会被视为(声明)在函数级作用域顶部的位置发生. function getValue(condition) { ...
- ES6快速入门(二)数据结构
ES6快速入门 一.解构 1. 对象解构 let person = { name: 'Tang', age: 28 }; //必须同名,必须初始化 let {name, age} = person; ...
- python 全栈开发,Day88(csrf_exempt,ES6 快速入门,Vue)
BBS项目内容回顾 1. 登陆页面 1. 验证码 1. PIL(Pillow) 2. io 2. ORM 1. 增删改查 3. AJAX $.ajax({ url: '', type: '', dat ...
- es6 快速入门 系列
es6 快速入门(未完结,持续更新中...) 前言 为什么要学习es6 es6对于所有javaScript开发者来说,非常重要 未来,es6将构成javaScript应用程序的基础 es6中很多特性, ...
- es6 快速入门 系列 —— 变量声明:let和const
其他章节请看: es6 快速入门 系列 变量声明:let和const 试图解决的问题 经典的 var 声明让人迷惑 function demo1(v){ if(v){ var color='red' ...
- es6 快速入门 系列 —— promise
其他章节请看: es6 快速入门 系列 Promise Promise 是一种异步编程的选择 初步认识Promise 用 Promise 来实现这样一个功能:发送一个 ajax,返回后输出 json ...
- es6快速入门 系列 - async
其他章节请看: es6 快速入门 系列 async 前文我们已经知道 promise 是一种异步编程的选择.而 async 是一种用于执行异步任务更简单的语法. Tip:建议学完 Promise 在看 ...
- es6 快速入门 系列 —— 类 (class)
其他章节请看: es6 快速入门 系列 类 类(class)是 javascript 新特性的一个重要组成部分,这一特性提供了一种更简洁的语法和更好的功能,可以让你通过一个安全.一致的方式来自定义对象 ...
- es6 快速入门 系列 —— 对象
其他章节请看: es6 快速入门 系列 对象 试图解决的问题 写法繁杂 属性初始值需要重复写 function createPeople(name, age){ // name 和 age 都写了 2 ...
随机推荐
- vue后台管理系统遇到的注意事项以及总结
地址栏加#号问题:Vue-router 中有hash模式和history模式,vue的路由默认是hash模式,一般开发的单页应用的URL都会带有#号的hash模式第一步在router/index.js ...
- Educational Codeforces Round 20
Educational Codeforces Round 20 A. Maximal Binary Matrix 直接从上到下从左到右填,注意只剩一个要填的位置的情况 view code //#pr ...
- Codeforces Round #625 (Div. 2, based on Technocup 2020 Final Round) A. Contest for Robots(数学)
题意: n 道题,2 个答题者,已知二者的做题情况,你是受贿裁判,可以给每题指定分值(≥1),求甲乙分数(甲>乙)相差最小时最大分值的最小值. 思路: 统计只有甲或乙做出的题目数. 加一取下整判 ...
- 【洛谷 p3381】模板-最小费用最大流(图论)
题目:给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 解法:在Dinic的基础下做spfa算法. 1 #include<cst ...
- Codeforces Round #696 (Div. 2) D. Cleaning (思维,前缀和)
题意:有一堆石子,你每次可以选择相邻(就算两堆石子中间有很多空堆也不算)的两堆石子,使得两堆石子的个数同时\(-1\),你在刚开始的时候有一次交换相邻石子的机会,问你最后能否拿走所有石子. 题解:对于 ...
- Codeforces Round #696 (Div. 2) C. Array Destruction (贪心,multiset)
题意:有\(n\)个数,首先任选一个正整数\(x\),然后在数组中找到两个和为\(x\)的数,然后去掉这两个数,\(x\)更新为两个数中较大的那个.问你最后时候能把所有数都去掉,如果能,输出最初的\( ...
- CodeForces - 916C 思维
题意:给你n,m,表示n个顶点和m条边,让你构造一个图. 要求 1.1->n最短路为素数 2.最小生成树边权和为prime 3.没有重边 4.边大小[1,1e9]. (题目给定m>n-1) ...
- K8S(09)交付实战-通过流水线构建dubbo服务
k8s交付实战-流水线构建dubbo服务 目录 k8s交付实战-流水线构建dubbo服务 1 jenkins流水线准备工作 1.1 参数构建要点 1.2 创建流水线 1.2.1 创建流水线 1.2.2 ...
- C++ part6.5
1.虚函数表建立和虚函数表指针初始化 虚拟函数表是在编译期就建立了,各个虚拟函数这时被组织成了一个虚拟函数的入口地址的数组.而虚函数表指针是在运行期,也就是构造函数被调用时进行初始化的,这是实现多态的 ...
- codevs1154能量项链 环形区间DP 细节
中文题..题意略 我们知道每次枚举最后合并哪两个.. 于是枚举中间节点k 我犯的错误是将转移方程写成了,dp[l][r]=max(dp[l][r],dp[l][k]+dp[k+1][r]+a[l]*a ...