第二章-函数

1 函数的定义和调用

  基本格式

function 函数名(参数列表){
    函数体
}

  函数体中的return一旦执行, 函数就不在执行而是返回了

  如果没有return, 则函数执行完毕就结束, 返回的值是undefined

  第二种函数定义

var 函数名 = function (参数列表){
    函数体  
};

  注意最后严谨一点加上分号表示赋值语句结束, 整个句子表示将函数赋值给一个变量, 该变量(参数列表) 就可以执行函数了

  调用函数

    函数名(参数列表);

    函数赋值的变量(参数列表);

  JavaScript有个十分随意的设定, 传入的参数是, 可以传入多余需要的参数, js会按照顺序得到需要的参数, 剩余的参数不管, 不会报错, 同理少传入参数也没有关系, 缺少的参数会设置为undefined

  在函数内部, 有个特殊变量arguments

  该变量存储传入进来的所有参数, 可以用类似于数组的方式获得数据

  

  配合arguments使用的是rest, 它可以排除函数定义的参数列表的参数

   

    当传入的参数少于参数列表的参数, rest得到的是一个空数组, 而不是undefined

  特殊注意:

    JavaScript尽管可以不加分号, 但是它实际上会在一行的末尾自动添加上分号

    这点就可能造成一下误会, 比如return与后面的返回值写成了两行, 那么其实际情况会是return; 返回语句;这样就出意外了

    

2 变量作用域

  在函数内定义的变量的作用域只是函数, 函数外面无法引用到函数内部定义的变量

  函数可以嵌套, 内部函数可以使用外部函数的变量, 但反过来不行

  变量的查找也是从内向外查找的

  特殊注意:变量提升

    JavaScript在函数中有一个十分诡异的操作

    它会先过一遍函数体, 然后把所有变量声明提到函数体首部

    

  因此在函数中, 一定要养成先定义变量的好习惯

   不在任何函数内定义的变量就具有全局作用域

  事实上, 是将该变量绑定给了特殊对象windows

   

  因此JavaScript只有一个全局作用域

  为了解决这个问题, 可以使用名字空间

  定义一个全局变量, 这个变量是个对象类型, 以后就往这个对象上添加内容就好了, 这样就会减少重名的情况

  for循环不能形成局部作用域, 要使得for中的变量是局部的, 需要使用关键字let

  let用于代替var声明一个块级作用域的变量

  常量, 名字的所有字母用大写形式表示, 尽管它确实可以被修改, 但是不要修改它

  常量可以用const来定义

3 方法

  绑定给对象的函数叫做方法

  在方法中, 有个特殊的变量this, 这个值始终指向当前对象

  

  但是如果直接调用计算age的方法, 就会出现预期之外的答案

  

  原因是, this会视情况而定指向谁, xiaoming.age就是执行的xiaoming, getAge()实际上是windows.getAge()所以指向的是windows

  可以使用apply或者来实现具体制定this指向

    apply(指向的对象, [原函数的参数列表])

    call(指向的对象, 原函数的参数列表)

    

  装饰器

    装饰器的意思是在不改变原有函数的基础上, 给其新增功能

    JavaScript的实现是, 将原来的函数保存起来, 在定义同名的函数, 这个函数内部先执行添加功能的代码, 再执行原函数

    代码如下

var count = 0;
var oldParseInt = parseInt;

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // 调用原函数
};

parseInt('10');
parseInt('20');
parseInt('30');
count; 

    记得使用原函数的时候, 要使用apply函数防止原函数中的this失效

4 高阶函数

  高阶函数, 这个函数的参数是另一个函数(一个函数作为另一个函数的参数, 这种函数就是高阶函数)

  (1) map和reduce

    扩展阅读: MapReduce: Simplified Data Processing on Large Clusters

    map会传入一个函数作为参数, 会让一个序列的所有值都让该函数执行, 然后将结果返回最后组成一个新的序列

    

    reduce方法是取两个参数给函数, 函数再返回一个结果加上一个新元素, 继续运算, 直到运算完毕

    

    奇怪的现象

    

  (2) filter

    filter用于过滤, 传入一个函数, 该函数的返回值是true和false, 当返回值为true时, 该值被保留, 为false时不保留

    

    filter接受的函数事实上是一个回调函数, 可以接受三个参数, 分别是: 元素, 索引, 调用者本身

    

    利用filter删除重复的元素

    

  (3) sort

    用于排序, 但是这个排序十分的诡异

    排序是按照ASCII的顺序排序的, 非字符串会转成字符串排序

    

    数字自己不能比较大小的吗? 嗯?

    

    因此sort()可以传入一个排序函数作为排序的手段, 用返回值标记大小, 如-1, 0, 1

    

5 闭包

  函数也可以作为结果, 被一个函数返回(返回值也可以是一个函数)

  闭包的应用

  

6 箭头函数

  箭头函数的定义基本格式是:

    (参数列表) => {函数体}

    如果函数体比较简陋, 就是一个表达式, 那么可以省略花括号和return

    如果返回一个对象, 对象的花括号要记得写

    注意, 如果使用箭头函数, 调用call和apply的时候, 平时传递的第一个参数对象时不会生效的, 箭头函数会直接忽略它

    

    可以看到结果是25而不是15

7 生成器

  在js中, 可以使用yield来生成生成器, 且函数同时还可以使用return关键字

  生成器形成之后需要调用next()来获取值

  可以直接使用for..of来获取全部结果

人若有恒 无所不成
原文地址:https://www.cnblogs.com/weihuchao/p/6909966.html