No1:
定义函数
function abs(x) { if (x >= 0) { return x; } else { return -x; } }
var abs = function (x) { if (x >= 0) { return x; } else { return -x; } };
由于JavaScript允许传入任意个参数而不影响调用,因此传入的参数比定义的参数多也没有问题,虽然函数内部并不需要这些参数:
abs(10, 'blablabla'); // 返回10 abs(-9, 'haha', 'hehe', null); // 返回9
传入的参数比定义的少也没有问题:
abs(); // 返回NaN
No2:
【arguments】
它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数
function foo(x) { console.log('x = ' + x); // 10 for (var i=0; i<arguments.length; i++) { console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30 } } foo(10, 20, 30, 40);
运行结果
x = 10 arg 0 = 10 arg 1 = 20 arg 2 = 30 arg 3 = 40
【rest】额外的参数
function foo(a, b, ...rest) { console.log('a = ' + a); console.log('b = ' + b); console.log(rest); } foo(1, 2, 3, 4, 5); // 结果: // a = 1 // b = 2 // Array [ 3, 4, 5 ] foo(1); // 结果: // a = 1 // b = undefined // Array []
No3:
JavaScript引擎在行末自动添加分号的机制
No4:
avaScript的函数在查找变量时从自身函数定义开始,从“内”向“外”查找。如果内部函数定义了与外部函数重名的变量,则内部函数的变量将“屏蔽”外部函数的变量
function foo() { var x = 1; function bar() { var x = 'A'; console.log('x in bar() = ' + x); // 'A' } console.log('x in foo() = ' + x); // 1 bar(); } foo();
运行结果
x in foo() = 1 x in bar() = A
No5:
【变量提升】
JavaScript的函数定义有个特点,它会先扫描整个函数体的语句,把所有申明的变量“提升”到函数顶部:
function foo() { var x = 'Hello, ' + y; console.log(x); var y = 'Bob'; } -------------相当于 function foo() { var y; // 提升变量y的申明,此时y为undefined var x = 'Hello, ' + y; console.log(x); y = 'Bob'; }
No6:
【let】
JavaScript的变量作用域实际上是函数内部,我们在for
循环等语句块中是无法定义具有局部作用域的变量的
function foo() { for (var i=0; i<100; i++) { // } i += 100; // 仍然可以引用变量i } -----------------修改为 function foo() { var sum = 0; for (let i=0; i<100; i++) { sum += i; } // SyntaxError: i += 1; }
No7:
【const】表示常量
No8:
【解构赋值】
var [x, y, z] = ['hello', 'JavaScript', 'ES6']; -------- let [x, [y, z]] = ['hello', ['JavaScript', 'ES6']]; -------- let [, , z] = ['hello', 'JavaScript', 'ES6']; -------- var person = { name: '小明', age: 20, gender: 'male', passport: 'G-12345678', school: 'No.4 middle school' }; var {name, age, passport} = person; -------- var person = { name: '小明', age: 20, gender: 'male', passport: 'G-12345678', school: 'No.4 middle school', address: { city: 'Beijing', street: 'No.1 Road', zipcode: '100001' } }; var {name, address: {city, zip}} = person; name; // '小明' city; // 'Beijing' zip; // undefined, 因为属性名是zipcode而不是zip // 注意: address不是变量,而是为了让city和zip获得嵌套的address对象的属性: address; // Uncaught ReferenceError: address is not defined -------- 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 -------- var person = { name: '小明', age: 20, gender: 'male', passport: 'G-12345678' }; // 如果person对象没有single属性,默认赋值为true: var {name, single=true} = person; name; // '小明' single; // true -------- ({x, y} = { name: '小明', x: 100, y: 200}); -------- var x=1, y=2; [x, y] = [y, x]
No9:
【方法】
var xiaoming = { name: '小明', birth: 1990, age: function () { var y = new Date().getFullYear(); return y - this.birth; } };
strict模式下让函数的this
指向undefined,所以上面改为
var xiaoming = { name: '小明', birth: 1990, age: function () { var that = this; // 在方法内部一开始就捕获this function getAgeFromBirth() { var y = new Date().getFullYear(); return y - that.birth; // 用that而不是this } return getAgeFromBirth(); } };
感觉真是吃饱了撑的
更新:优化如下
var obj = { birth: 1990, getAge: function () { var b = this.birth; // 1990 var fn = () => new Date().getFullYear() - this.birth; // this指向obj对象 return fn(); } }; obj.getAge(); // 25
No10:
【高阶函数】
function add(x, y, f) { return f(x) + f(y); }
由于map()
方法定义在JavaScript的Array
中,我们调用Array
的map()
方法,传入我们自己的函数,就得到了一个新的Array
作为结果
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);
运行结果
1,4,9,16,25,36,49,64,81
No11:
【reduce】
[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
var arr = [1, 3, 5, 7, 9]; arr.reduce(function (x, y) { return x + y; }); // 25
No12:
【filter】
var arr = [1, 2, 4, 5, 6, 9, 10, 15]; var r = arr.filter(function (x) { return x % 2 !== 0; }); r; // [1, 5, 9, 15]
去除Array
的重复元素
var r, arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry']; r = arr.filter(function (element, index, self) { return self.indexOf(element) === index; }); console.log(r.toString());
No13:
【sort】
Array
的sort()
方法默认把所有元素先转换为String再排序
数字大小排序
var arr = [10, 20, 1, 2]; arr.sort(function (x, y) { if (x < y) { return -1; } if (x > y) { return 1; } return 0; }); console.log(arr); // [1, 2, 10, 20]
sort()
方法会直接对Array
进行修改,它返回的结果仍是当前Array
var a1 = ['B', 'A', 'C']; var a2 = a1.sort(); a1; // ['A', 'B', 'C'] a2; // ['A', 'B', 'C'] a1 === a2; // true, a1和a2是同一对象
No14:
【函数作为返回值】
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]); f(); // 15
No15:
匿名函数并立刻执行
(function (x) { return x * x }) (3);
常用函数
function make_pow(n) { return function (x) { return Math.pow(x, n); } } // 创建两个新函数: var pow2 = make_pow(2); var pow3 = make_pow(3); console.log(pow2(5)); // 25 console.log(pow3(7)); // 343
No16:
【箭头函数】
x => x * x 相当于 function (x) { return x * x; }
箭头函数相当于匿名函数,并且简化了函数定义
x => { if (x > 0) { return x * x; } else { return - x * x; } }
// 两个参数: (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 })
No17:
【generator】
generator由function*
定义(注意多出的*
号),并且,除了return
语句,还可以用yield
返回多次
function* foo(x) { yield x + 1; yield x + 2; return x + 3; }
斐波那契
function* fib(max) { var t, a = 0, b = 1, n = 0; while (n < max) { yield a; [a, b] = [b, a + b]; n ++; } return; }
调用
for (var x of fib(10)) { console.log(x); // 依次输出0, 1, 1, 2, 3, ... }
学到这里,我感觉js有些知识点还是挺难理解的,不管怎样,先硬着头皮学吧