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

getvalue函数怎么使用_深入理解ES6函数_第1张图片

作者:一声蔷薇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 -

getvalue函数怎么使用_深入理解ES6函数_第2张图片

getvalue函数怎么使用_深入理解ES6函数_第3张图片

你可能感兴趣的:(getvalue函数怎么使用)