函数总结

2018-05-11  本文已影响3人  磁针石
定义
function abs(x)
{
//argument 所有参数的数组;rest是剩余参数数组
  ...
}
函数是一个对象,匿名函数赋值 `abs` 对象 可定义为:
var abs = function(x)
{
  ...
};

'use strict';

const PI = 3.14;
PI = 3; // 某些浏览器不报错,但是无效果!
PI; // 3.14

var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
如果数组本身还有嵌套注意嵌套层次和位置要保持一致:let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']];
解构赋值还可以忽略某些元素:let [, , z] = ['hello', 'JavaScript', 'ES6']; // 忽略前两个元素,只对z赋值第三个元素
如果需要从一个对象中取出若干属性,也可以使用解构赋值,便于快速获取对象的指定属性,变量名和属性名应保持一致,如果不一致,使用{属性名:变量名} = 对象

var person = {
    name: '小明',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
};

// 把passport属性赋值给变量id:
let {name, passport:id} = person;
name; // '小明'
id; // 'G-12345678'
// 注意: passport不是变量,而是为了让变量id获得passport属性:
passport; // Uncaught ReferenceError: passport is not defined
// 如果person对象没有single属性,默认赋值为true:
var {name, single=true} = person;

交换变量值
var x=1, y=2;
[x, y] = [y, x]
高阶函数可把函数作为一个参数,还可以把函数作为结果值返回
'use strict';

function pow(x) {
    return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
var results = arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
console.log(results);
var arr = ['A', '', 'B', null, undefined, 'C', '  '];
var r = arr.filter(function (s) {
    return s && s.trim(); // 注意:IE9以下的版本没有trim()方法
});
r; // ['A', 'B', 'C']
数组去重
r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index;
});
function sum(arr) {
    return arr.reduce(function (x, y) {
        return x + y;
    });
}

sum([1, 2, 3, 4, 5]); // 15

但是,如果不需要立刻求和,而是在后面的代码中,根据需要再计算怎么办?可以不返回求和的结果,而是返回求和的函数!
function lazy_sum(arr) {
    var sum = function () {
        return arr.reduce(function (x, y) {
            return x + y;
        });
    }
    return sum;
}
var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()
f(); //15调用函数f时,才真正计算求和的结果

我们调用lazy_sum()时,每次调用都会返回一个新的函数,即使传入相同的参数
var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; // false

注意到返回的函数在其定义内部引用了局部变量arr,
所以,当一个函数返回了一个函数后,其内部的局部变量还被新函数引用。
返回闭包时牢记的一点就是:返回函数不要引用任何循环变量,或者后续会发生变化的变量。
function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i;
        });
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];
f1(); // 16
f2(); // 16
f3(); // 16
改进版:
function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i));
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9
注意这里用了一个“创建一个匿名函数并立刻执行”的语法:
(function (x) {
    return x * x;
})(3); // 9
Java和C++,要在对象内部封装一个私有变量,可以用private修饰一个成员变量。
在没有class机制,只有函数的语言里,借助闭包,同样可以封装一个私有变量。我们用JavaScript创建一个计数器:
function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;
        }
    }
}
var c1 = create_counter();
c1.inc(); // 1
c1.inc(); // 2
c1.inc(); // 3
// 两个参数:
(x, y) => x * x + y * y

// 无参数:
() => 3.14

// 可变参数:
(x, y, ...rest) => {
   var i, sum = x + y;
   for (i=0; i<rest.length; i++) {
       sum += rest[i];
   }
   return sum;
}
如果要返回一个对象`x => ({ foo: x })`
箭头函数内部的this是词法作用域,由上下文确定。
function* fib(max) {
    var
        t,
        a = 0,
        b = 1,
        n = 0;
    while (n < max) {
        yield a;
        [a, b] = [b, a + b];
        n ++;
    }
    return;
}
var f = fib(5);
f.next(); // {value: 0, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 1, done: false}
f.next(); // {value: 2, done: false}
f.next(); // {value: 3, done: false}
f.next(); // {value: undefined, done: true}
`fib(5)`仅仅是创建了一个`generator`对象,还没有去执行它
调用generator对象有两个方法,一是不断地调用generator对象的next()方法,next()方法会执行generator的代码,
每次遇到yield x;就返回一个对象{value: x, done: true/false},
然后“暂停”。返回的value就是yield的返回值,done表示这个generator是否已经执行结束了.
第二个方法是直接用for ... of循环迭代generator对象,这种方式不需要我们自己判断done:
for (var x of fib(10)) {
    console.log(x); // 依次输出0, 1, 1, 2, 3, ...
}

上一篇 下一篇

猜你喜欢

热点阅读