javascript忍者秘籍-第三章 函数定义与参数

函数的定义与参数

JavaScript 作为函数式语言来理解。

关键概念

函数是第一类对象(一等公民)

函数可以看作是 其他任意类型的 Javascript 对象

函数和其他的数据类型一样,能被变量引用,以字面量形式声明,作为函数参数传递

发现

:musical_note: 在需要调用某函数的位置 定义该函数,能让代码更紧凑、更易懂

术语

一等公民

一般来说,如果某程序设计语言中的一个值可以作为 参数传递,可以从 子程序中返回,可以 赋值给变量,就称为一等公民

二等公民

可以作为 参数传递,但是不能从子程序中返回,也不能赋值给变量

三等公民

值连作为参数传递都不行(label)

3.1 函数式的不同点

与对象的不同

对象的常见功能

  1. 对象可通过字面量来创建 {}

    var lsObj = {};
    复制代码
  2. 对象可以赋值给变量、数组项,或其他对象的属性

    var lsObj = {};
    lsArray.push({});
    lsObj.data = {}
    复制代码
  3. 对象可以作为参数传递给函数

    function hide(obj){
        obj.visibility = false;
    }
    hide({});
    复制代码
  4. 对象可以作为函数的返回值

    function returnNewLs(){
        return {};
    }
    复制代码
  5. 对象能够具有动态创建和分配的属性

    var lsObj = {};
    lsObj.name = "lisi";
    复制代码

函数是第一类对象

函数拥有对象的所有能力,所以函数可被看作 任意其他类型 的对象

函数也具有对象的功能

  1. 通过字面量创建

    function ninjaFunction(){}
    复制代码
  2. 赋值给变量、数组项或其他对象的属性

    var ninjaFunction = function(){};   //为变量赋值一个新函数
    ninjaArray.push(function(){});      //向数组中增加一个新函数
    ninja.data = function(){};          //给某个对象的属性赋值一个新函数
    复制代码
  3. 作为函数的参数传递

    function call(ninjaFunction){
        ninjaFunction();
    }
    //新函数作为参数传递给函数
    call(function(){});
    复制代码
  4. 作为函数的返回值

    //返回一个新函数
    function returnNewNinjaFunction(){
        return function(){};
    }
    复制代码
  5. 动态创建的属性

    //为函数增加一个新属性
    var ninjaFunction = function(){};
    ninjaFunction.ninja = "Hanzo";
    复制代码

:eight_pointed_black_star: 函数也是对象,函数与对象的不同在于:==函数是可调用的==

:v: 第一类对象的特点之一:能够作为参数传入函数

对于函数来说这个特性表明:将某个函数作为参数传入另一个函数,传入的函数会在将来的某个时刻执行。由此推出 【回调函数】

回调函数

浏览器的回调函数(计时器函数)和我们自定义的回调函数

回调不一定是异步的

浏览器回调

document.body.addEventListener("mousemove",function(){...})
复制代码

自定义的回调

排序方法sort,可以传入一个函数进行排序

var values = [0,3,2,7,1,8];
values.sort(function(value1,value2){
    return value1 - value2;
});
复制代码

? 函数式方式 把 函数当作一个 单独实体 来创建,与其他类型一样,创建、作为参数传递和返回。函数显示了一等公民的地位。

function(value1,value2){} 是一个整体,类似 abc

3.2 函数作为对象

类似对象,函数也可以添加属性

//对象
var ninja = {};
ninja.name = 'hitsuke';

//函数
var wieldSword = function(){};
wieldSword.swordType = "katana";
复制代码

存储函数

函数的属性作为值

:question: 管理一个元素的所有回调函数集合,相同的回调只存储一次

//存储唯一函数集合
var store = {
    nextId : 1,
    cache : {},
    add : function(fn){
        if(!fn.id){
            fn.id = this.nextId++;
            this.cache[fn.id] = fn;
            return true;
        }
    }
}

function ninja(){}

store.add(ninja);  //true  ninja.id 存在了  
//Object.getOwnPropertyNames(ninja) (6) ["length", "name", "arguments", "caller", "prototype", "id"]
store.add(ninja);  //undefined
复制代码

缓存结果

函数的属性作为对象

//计算先前得到的值
function isPrime(value){
    if(!isPrime.answers){
        isPrime.answers = {};  //创建缓存
    }
    if(isPrime.answers[value] !== undefined){
        return isPrime.answers[value];  //检查缓存的值 并 返回
    }
    var prime = value !== 0 && value !== 1;
    for(var i = 2;i < value; i++){
        if(value % i === 0){
            prime = false;
            break;
        }
    }
    return isPrime.answers[value] = prime;  //存储计算的值
}

isPrime(5);
isPrime.answers[5];
复制代码

3.3 函数定义

JavaScript 定义函数的几种方式

  1. 函数声明和函数表达式

    function abc(){}
    
    var abc = function(){}
    复制代码
  2. 箭头函数 lambda函数

    myArg => myArg * 2
    复制代码
  3. 函数构造函数

    new Function('a','b','return a + b')
    复制代码
  4. 生成器函数

    //函数退出再进入时,之前的变量值被保存
    function* myGen(){ yield 1; }
    复制代码

函数声明和函数表达式

//函数声明强制以 function 开头;作为一个单独的JavaScript语句,函数声明必须独立
function samurai(){
    return "samurai here";
}

function ninja(){
    function hiddenNinja(){
        return "ninja here";
    }
    return hiddenNinja();
}
复制代码
//函数表达式 作为 赋值表达式的右值 、作为其他函数的参数
var myFunc = function(){};

myFunc(function(){
    return function(){};
});
复制代码

对于函数声明来说,函数名是强制性的,对于函数表达式来说,函数名是可选的。

立即执行函数

一般包裹在一对括号内:JavaScript解析器必须轻易区分 函数声明和函数表达式的区别。

函数表达式放在括号内,为JavaScript解析器指明:它正在处理一个函数表达式而不是语句。

myFunctionName(3);

//IIFE 立即函数
(function(){})(3)

(function namedFunctionExpression(){})();  //立即调用

//函数表达式作为一元操作符的参数立即调用
//为JS引擎指明 处理的是表达式,而不是语句
+function(){}();
-function(){}();
!function(){}();
~function(){}();
复制代码

箭头函数

箭头函数是函数表达式的简化版

//箭头函数的语法
//箭头函数接收一个参数并返回表达式的值
param => expression

//如果没有参数或多于一个参数,参数列表必须包裹在括号内
//如果只有一个参数,括号不是必须的
var greet = name => "Greeting " + name;

var greet = () => "Greeting";
var greet = (name,age) => "hello " + name + age;

//胖箭头 操作符后面可以是 表达式 也可以是代码块
var greet = name => "Greeting" + name;

var greet = (name,age) => {
    return name + age;
}
复制代码
var values = [1,2,3,5,8];
values.sort(function(value1,value2){
    return value1 - value2;
});

//箭头函数
values.sort((value1,value2) => value1 - value2);
复制代码

3.4 函数的实参和形参

如果函数的 实参数量 > 形参数量 , 多余的不会分配给形参

如果函数的 实参数量 < 形参数量 , 对应的形参赋值为 undefined

剩余参数

只有函数的最后一个参数才能是剩余参数。

给函数的最后一个形参加上省略号(…)前缀,这个参数就变成了一个 剩余参数的数组 。数组内包含着传入的剩余的参数。

function multiMax(first, ...remainingNumbers){
    ...
}
复制代码

默认参数

为函数的参数提供一个默认参数

默认参数可以是任意值:数字、字符串、对象、数组、甚至是函数

后面的默认参数 可以引用 前面的默认参数

function performAction(ninja, action){
    action = typeof action === "undefined" ? "skulking" : action;
    return ninja + " " + action;
}

function performAction(ninja, action = "skulking"){
    return ninja + " " + action;
}

function performAction(ninja, action = "skulking", message = ninja + " " + action){
    return message;
}
复制代码

typeof 操作符返回一个字符串 用于表明操作数的类型。如果操作数未定义,则返回字符串 "undefined"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值