getvalue函数怎么使用_深入理解ES6函数

ddf4fd9523484bafac03e04f03e7edda.png

作者:一声蔷薇udVkP

来源:SegmentFault 思否社区


函数形参默认值

1、es5、es6对默认参数的处理区别:

es5:形参默认值是要先判断,参数是否有值,如果没有在赋值

es6:在定义函数时,可以直接给形参添加默认值,当函数调用实参为undefined则给形参赋值为默认值

注意:当传进来的值为null,则不调用默认参数

2、默认参数对argument的影响

1、影响argument的length属性

2、命名参数的变化不会跟新同步到argument对象中

es5非严格模式下。参数的变化会同步到argument中,严格模式下则不会

es6只要函数使用默认参数,无论是否显示定义严格模式都使得arguments对象保持与命名参数分离

例子-非严格模式:

function minArgs(first,second ="b"){

console.log(argument.length)

console.log(first===argument[0])

console.log(second===argument[1])

first = "c";

second = "d";

console.log(first===argument[0])

console.log(second===argument[1])

}

minArgs("a")

// 1

//true

//false

//false

//false

默认参数表达式

1、可以使用函数调用结果作为默认参数

2、可以使用先定义的参数作为函数调用的默认参数

3、先定义参数不能访问后定义参数,这是因为后定义的参数临时死区(TDZ)

例子-函数调用结果作为默认参数:

let value =5

function getValue(){

return value++

}

function add(a,b=getValue()){

return a+b

}

console.log(add(1,2))//3

console.log(add(1))//6

不定参数


1、概述:

es5中无命名参数-argument:记录所有传进来的实参

es6中不定参数-(...):记录自这个参数后传进来的所有参数,使用上会更加方便

2、不定参数的使用限制:

a:每个函数只能声明一个不定参数

b:不定参数只能放在末尾

c:不定参数不能用于对象字面量的setter中

3、不定参数对argument的影响:

无影响

展开运算符(...)


概念:

1、不定参数是可以让你指定多个参数,整合成数组

2、展开运算符是让你指定数组,将他们打散后作为各种独立的参数传入函数

增强Function构造函数


目的:用来动态创建新函数

参数:字符串形式的参数,分别为函数参数,函数体

支持创建函数时使用默认参数和不定参数

例子:

var add = new Function0("first","second","return first+second")

console.log(add(1,2))//3

//默认参数

var add1 = new Function0("first","second=first","return first+second")

console.log(add1(1))//2

//不定参数

var add2 = new Function0("...args","return args[0]")

console.log(add2(1,2,3))//1

name属性


1、目的:用于辨别函数

2、如何选择合适的名称:

函数声明:

function doSomething(){}

doSomething.name = doSomething

匿名函数表达式

let doAnotherThing = function(){}

doAnotherThing.name = doAnotherThing

3、name的特殊情况

情况1:

let doSomethingElse = function doSomething(){}

doSomethingElse.name =doSomething

情况2:

var person={

get firstName(){

},

sayName:function(){

}

}

person.firstName().name = "get firstName"

(getter函数和setter函数会再name属性前加一个前缀"get"、"set")

person.sayName().name = "sayName"

情况3:

通过bind()函数创建的,名称带有"bound"前缀

情况4:

通过mew Function创建的,名称为"anonymous"

注意:不能使用name属性值来获取对函数的引用

函数的两种用途


  1. 结合new使用,函数返回一个新对象,this指向实例

  2. 直接调用

判断函数是通过什么方式调用

js函数有两个不同的内部方法[[Call]]和[[Construct]]

当通过new调用,执行[[Construct]],否则执行[[Call]]

es5判断函数的调用方式:instanceof

当通过new调用的时候,可以检查this的值是否为构造函数的实例

function Person(name){

    if(this instanceof Person){

        this.name = name;

    }else{

        throw new Error("必须通过构造函数调用")

    }

}

var person = new Person("lisi")//有效

var p1 = Person.call(Person,"wangwu")//有效

var p2 = Person("dd")//Error("必须通过构造函数调用")

弊端:通过instanceof 不能准确判断这个函数是不是new调用,因为通过call或者apply等方法也可以改变this的指向,让this指向某个实例

es6判断函数调用方式:元属性->new.target

元属性:非对象的属性,可以提供非对象目标的补充信息(例如new)

当通过new调用,new.target被赋值为新创建对象的实例,也就是函数体内this构造函数,否则值为undefined

例子:

function Person(name){

    //if(new.target === Person)

    if(typeof new.target !=="undefined"){

        this.name = name;

    }else{

        throw new Error("必须通过构造函数调用")

    }

}

var person = new Person("lisi")//有效

var p1 = Person.call(Person,"wangwu")//抛出错误

注意:new.target只能在函数体内使用,否则报错

块及函数


1、在es3之前版本在代码块中声明一个函数,会被认定是一个错误

2、最好不要在代码块中使用函数声明,推荐用函数表达式

3、由于不同浏览器兼容不同,所以es5严格模式下,代码块中声明一个函数时程序会抛出错误

4、es6会将声明的函数视为一个块及函数

例子:

if(true){

    console.log(typeof doSomething)//"function"

    //块级函数

    function doSomething(){

        console.log("ss");

    }

    doSomething()

    //let函数表达式

    let doSomethingElse = function(){

    }

}

console.log(doSomething()) //undefined

讲解:定义函数的代码块中,函数会被提升到顶部,一旦if语句代码块结束执行,doSomething()不复存在。块级函数和let函数表达式类似,一旦执行过程流出代码块,函数定义立即被移除,区别是,块级函数会被提升到代码块顶部,let定义的函数表达式不会被提升。

es6非严格模式,块级函数会被提升到全局作用域

箭头函数


特点:

1、没有this,super,arguments,new.target的绑定,箭头函数的this、arguments,new.target这些值由外围最近一层非箭头函数决定

2、不能通过new关键字调用

3、没有原型,所以不存在prototype属性

4、不可改变this的绑定,函数体内部的this值不可被该变

5、不支持arguments对象,始终可以访问外围的arguments对象

6、不支持重复命名参数

语法:

参数、箭头、函数体组成

情况一:当只有一个参数时:

let reflect = value=>value

相当于:

let reflect = function(value){

    return value

}

情况二:两个参数时,参数用括号括起来

情况三:没有参数时,直接一个括号后面跟箭头和函数体

情况四:如果想让箭头函数向外返回一个对象字面量,将该字面量包裹在小括号里

let getTempItem = ()=>({name:"zhangsan",age:17})

相当于

let getTempItem = function(){

    return {

    name:"zhangsan",

    age:17

    }

}

情况五:创建立即执行函数表达式:

let person = ((name)=>{

    return {

        getName(){

            return name

        }

    }

})("kankan")

用小括号包裹箭头函数定义,不包括调用实际参数部分

箭头函数的this值:取决于外部非箭头函数的this值

箭头函数设计初衷:即用即弃。

function pageHandle(){

    id:123,

    init:function(){

        document.addEnventListener("click",event=>this.doSomething(event.typ))

    },

    doSomethis(type){

     console.log(type)

    }

}

尾调用优化


尾调用:函数作为另一个函数的最后一条语句被调用

es5引擎中,尾调用实现和其他函数调用实现类似,创建一个栈帧,将其推入调用栈表示函数调用,每一个未用完的栈帧都会保存在内存中,当调用栈变得过大会造成程序问题

es6严格模式下满足以下3个条件,尾调用不创建栈帧,而是清除并重用当前栈帧

1、尾调用不访问当前栈帧的变量(不是闭包)

2、在函数内部,尾调用是最后一条语句

3、尾调用结果作为函数值返回

例:(可以被js引擎自动优化)

"use strict"



function test(){

    return doSomething()

}

递归函数是其最主要的应用场景,优化效果显著

function factorial(n){

    if(n<=1){

        return 1

    }else{

        return n*factorial(n-1)

    }

}

在递归调用前执行了乘法操作,所以当前阶乘函数无法优化

function factorial(n,p=1){

    if(n<=1){

        return 1*p

    }else{

        let result = n*p

        优化后

        return factorial(n-1,result)

    }

}

可以被优化,如果递归函数足够大,可以大幅提升程序性能


- END -

92bbd878a9b81afa6d1ce1acf24b3876.png

068232769dfbc6f0eaf6add212e63862.gif

<think>好的,用户问的是箭头函数怎么使用。之前他们问过reduce是不是遍历函数,我详细解释了reduce的用法和应用场景,现在他们可能在学习ES6的新特性,特别是箭头函数。箭头函数在JavaScript中确实是个重要的知识点,但用户可能对它的语法和应用不太清楚。 首先,我需要确定用户的基础。他们可能已经了解传统函数表达式,但想简化代码或者理解箭头函数的特性。要解释箭头函数的基本语法,对比传统函数,强调简洁性。比如,单参数可以省略括号,单行代码可以省略return和花括号。 然后,用户可能想知道箭头函数和普通函数的区别,尤其是this的指向问题。这里需要重点说明箭头函数没有自己的this,而是继承外层作用域,这对于事件处理或者回调函数中的this行为很重要。比如在setTimeout里使用箭头函数,this不会丢失上下文。 另外,箭头函数不能作为构造函数,不能用new调用,这点需要提醒用户避免错误使用。还要提到没有arguments对象,需要用剩余参数代替。这些限制对于习惯传统函数的开发者来说可能容易出错,所以需要强调。 接下来,应用场景部分要给出实际例子,比如数组方法map、filter,简化回调函数,或者用在需要固定this的地方。比如在Vue或React中处理事件时,箭头函数可以保持this指向组件实例。 用户可能的深层需求是希望写出更简洁、现代的代码,或者解决this指向的问题。他们可能在项目中遇到相关问题,或者在学习过程中看到别人使用箭头函数,想掌握其正确用法。需要确保回答结构清晰,从基础到高级,逐步深入,同时给出对比示例,帮助理解差异。 还要注意用户可能存在的误区,比如认为箭头函数完全替代传统函数,但实际上某些情况还是需要传统函数,比如需要动态this的方法。这时候需要指出适用场景和限制,避免混淆。 最后,总结箭头函数的优缺点,让用户明确何时使用,何时不用。确保回答准确、实用,帮助他们正确应用箭头函数,提升代码质量。</think>--- ### 一、箭头函数基础语法 箭头函数(Arrow Function)是 ES6 新增的**简化函数定义**的语法,核心特征是 `=>` 符号和自动绑定上下文。 #### 1. 基本格式对比 | 传统函数 | 箭头函数 | |-----------------------------------|-----------------------------------| | `function(a) { return a + 1; }` | `a => a + 1` | | `function(a,b) { return a + b; }` | `(a,b) => a + b` | | `function() { return 5; }` | `() => 5` | #### 2. 语法规则 - **单参数**可省略括号: `x => x * 2` ✅ `(x) => x * 2` ✅ `x, y => x + y` ❌(多参数必须加括号) - **单行代码**自动返回结果(无需 `return` 和 `{}`): `items.map(item => item.id)` ✅ `items.map(item => { item.id })` ❌(会返回 `undefined`,需显式 `return`) - **多行代码**需用 `{}` 包裹并显式返回: ```javascript (x, y) => { const sum = x + y; return sum * 2; // 必须手动返回 } ``` --- ### 二、与传统函数的三大核心差异 #### 1. 没有独立的 `this`(最重要特性) ```javascript // 传统函数 const obj = { value: 10, getValue: function() { setTimeout(function() { console.log(this.value); // 输出 undefined(this指向window) }, 100); } }; // 箭头函数 const obj = { value: 10, getValue: function() { setTimeout(() => { console.log(this.value); // 输出 10(继承外层this) }, 100); } }; ``` #### 2. 不能作为构造函数 ```javascript const Person = (name) => { this.name = name }; // ❌ new Person("Alice"); // TypeError: Person is not a constructor // 正确做法:使用传统函数 function Person(name) { this.name = name }; // ✅ ``` #### 3. 没有 `arguments` 对象 ```javascript const sum = () => { console.log(arguments); // ❌ 报错:arguments未定义 }; // 替代方案:使用剩余参数 const sum = (...args) => { console.log(args); // ✅ 输出参数数组 }; ``` --- ### 三、典型应用场景 #### 1. 简化数组方法回调 ```javascript // 传统写法 [1, 2, 3].map(function(num) { return num * 2 }); // 箭头函数写法 [1, 2, 3].map(num => num * 2); // [2, 4, 6] ``` #### 2. 保持上下文(React/Vue 事件处理) ```javascript // React 类组件示例 class Button extends React.Component { state = { count: 0 }; // 传统函数需要绑定this handleClick() { this.setState({ count: this.state.count + 1 }); } // 箭头函数自动绑定this handleClick = () => { this.setState({ count: this.state.count + 1 }); }; render() { return <button onClick={this.handleClick}>点击</button>; } } ``` #### 3. 简化对象属性方法 ```javascript // 传统写法 const calculator = { add: function(a, b) { return a + b } }; // 箭头函数写法 const calculator = { add: (a, b) => a + b }; ``` --- ### 四、应避免使用箭头函数的情况 | 场景 | 问题示例 | 解决方案 | |--------------------------|-----------------------------------|------------------------------| | 对象原型方法 | `Person.prototype.getName = () => this.name` ❌(this指向错误) | 使用传统函数 | | DOM 事件回调(需要this)| `button.addEventListener('click', () => { this.style.color = 'red' })` ❌ | 用 `function` 或 `bind` | | 需要动态改变this的函数 | 需要 `call()`/`apply()` 改变上下文时 ❌ | 改用传统函数 | --- ### 五、综合对比表 | 特性 | 传统函数 | 箭头函数 | |---------------------|------------------------------|------------------------------| | `this` 指向 | 动态绑定(谁调用指向谁) | 静态绑定(定义时外层this) | | 构造函数能力 | ✅ | ❌ | | `arguments` 对象 | ✅ | ❌(需用剩余参数 `...args`) | | 适合场景 | 需要动态this、构造函数 | 需要固定this、简单回调 | --- ### 六、进阶用法示例 #### 1. 链式操作 ```javascript const operations = { value: 1, add: (x) => ({ value: operations.value + x, multiply: (y) => ({ value: (operations.value + x) * y }) }) }; console.log(operations.add(2).multiply(3)); // { value: (1+2)*3=9 } ``` #### 2. 立即执行函数(IIFE) ```javascript // 传统写法 (function() { console.log("立即执行"); })(); // 箭头函数写法 (() => { console.log("立即执行"); })(); ``` --- 掌握箭头函数的关键在于理解其**词法作用域的 `this`** 和**简洁语法**,在需要保持上下文或简化代码时优先使用,但在需要动态绑定或构造对象时仍需依赖传统函数
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值