===与==
== 自动转换数据类型再比较; === 不转换类型 (更好) 例外: NaN === NaN // false
字符串
使用反引号来表示多行字符串
var a = `这是一个
多行
字符串`;
字符串不可变:使用a[0] = 'X'并没有改变效果
数组
直接给array的length赋新值会改变Array的大小; length变大则新增元素为undefined;变小则删除超出长度的元素;
数组方法
slice // 不加参数可以用于复制数组,不改变本身
pop
push
unshift // 在头部添加
shift // 在头部删除
sort // 字母排序
reverse // 反转
splice // 从指定索引删除若干元素,在从该位置添加若干元素
concat // 拼接,返回新Array
join // 使用指定字符拼接数组元素 ==> String
Map 键值对结构,大数据量时具有极快的查找速度
根据key值迅速获取对应value
var m = new Map([['Michael', 95], ['Bob', 75], ['Tracy', 85]]);
m.get('Michael'); // 95
m.set('Adam', 67); // 添加新的key-value
m.set('Bob', 59);
m.has('Adam'); // 是否存在key 'Adam': true
m.get('Adam'); // 67
m.delete('Adam'); // 删除key 'Adam'
m.get('Adam'); // undefined
Set 只有非重复key,没有value值
var s = new Set([1, 2, 3, 3, '3']);
s; // Set {1, 2, 3, "3"}
// 添加元素
s.add(4);
s; // {1, 2, 3, 4}
// 删除元素
s.delete(3);
iterable类型
包括Array、Map、Set等; for。。。in 循环对象的属性名称key;一个Array数组实际上也是一个对象,它的每个元素的索引被视为一个属性。 for。。。of 循环对象键值对中的value;更适合遍历没有key的集合,如Set; forEach方法 (更好)
a.forEach(function (element, index, array) {
// element: 指向当前元素的值
// index: 指向当前索引
// array: 指向Array对象本身
alert(element);
});
// Set与Array类似,但Set没有索引,因此回调函数的前两个参数都是元素本身:
// Map的回调函数参数依次为value、key和map本身:
函数arguments参数
它只在函数内部起作用,并且永远指向当前函数的调用者传入的所有参数。arguments类似Array但它不是一个Array: 利用arguments,你可以获得调用者传入的所有参数。即使函数不定义任何参数,还是可以拿到参数的值
当传入参数个数超过函数定义的参数个数,则将多余参数传入rest参数。
// rest参数只能写在最后,前面用...标识
// 传入的参数先绑定a、b,多余的参数以数组形式交给变量rest
// 所以,不再需要arguments我们就获取了全部参数。
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 []
全局对象 window
全局作用域的变量实际绑定到window的一个属性
'use strict';
var course = 'Learn JavaScript';
alert(course); // 'Learn JavaScript'
alert(window.course); // 'Learn JavaScript'
// 全局变量course 等同于 window.course
// alert函数也是window的一个变量
减少全局变量的冲突:声明一个唯一的全局变量{};然后把所有变量和函数都绑定到这个唯一一个全局变量上。
局部作用域
for循环中,var i可以在循环块外部被引用;ES6的let i则解决了这个问题。
'use strict';
function foo() {
for (var i=0; i<100; i++) {
//
}
i += 100; // 仍然可以引用变量i
}
'use strict';
function foo() {
var sum = 0;
for (let i=0; i<100; i++) {
sum += i;
}
i += 1; // SyntaxError
}
this丢失问题
对象方法中的this,必须由对象进行调用该方法才能获取this; 对象方法中的函数,this指向全局对象window; 解决方法1: that
// 保存当前this ===> that
'use strict';
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();
}
};
xiaoming.age(); // 25
解决方法2: apply与call
// 使用apply或call,控制函数的this指向传入的首个参数
function getAge() {
var y = new Date().getFullYear();
return y - this.birth;
}
var xiaoming = {
name: '小明',
birth: 1990,
age: getAge
};
xiaoming.age(); // 25
// apply()把参数打包成Array再传入;
getAge.apply(xiaoming, []); // 25, this指向xiaoming, 参数为空
// 把参数按顺序传入。
getAge.call(xiaoming)
解决方法3: IFEE思想,bind(this)
高阶函数
函数参数`指向`函数
map逐一映射
// *****
// “把f(x)作用在Array的每一个元素并把结果生成一个新的Array”。
// *****
function pow(x) {
return x * x;
}
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
arr.map(pow); // [1, 4, 9, 16, 25, 36, 49, 64, 81]
reduce瀑布映射
原理:[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)
// *****
// 把结果继续和序列的下一个元素做累积计算
// *****
// [1, 3, 5, 7, 9]变换成整数13579,reduce()也能派上用场:
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
return x * 10 + y;
}); // 13579
filter过滤
filter()把传入的函数依次作用于每个元素,然后根据返回值是true还是false决定保留还是丢弃该元素。
// 利用filter,可以巧妙地去除Array的重复元素:
'use strict';
var r,
arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
r = arr.filter(function (element, index, self) {
// indexOf总是返回第一个元素的位置,后续的重复元素位置与indexOf返回的位置不相等,被过滤
return self.indexOf(element) === index;
});
alert(r.toString());
sort 排序
sort()方法会直接对Array进行修改,它返回的结果仍是当前Array: 默认把所有元素先转换为String再排序,字符串根据首个字符的ASCII码进行排序 sort的自定义排序中,return -1不对调;return 1对调;
// 升序排列
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
if (x < y) {
return -1;
}
if (x > y) {
return 1;
}
return 0;
}); // [1, 2, 10, 20]
箭头函数
x => x * x
等同于
function (x) {
return x * x;
}
箭头函数相当于匿名函数 格式一,只包含一个表达式,可以省略{ ... }和return 格式二,包含多条语句,不能省略{ ... }和return:
参数
// 两个参数:
(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;
}
返回对象
返回对象时存在语法冲突{} 所以改为({foo:x})
this作用域
箭头函数修复了this的指向,this总是指向词法作用域,也就是外层调用者obj: 也就是说,在对象(第一层)的方法(第二层)的函数(第三层)中,仍然可以用this调用到对象的属性值;
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
call()与apply()
由于this在箭头函数中已经按照词法作用域绑定了,所以,用call()或者apply()调用箭头函数时,无法对this进行绑定,即传入的第一个参数被忽略,直接传入参数即可
var obj = {
birth: 1990,
getAge: function (year) {
var b = this.birth; // 1990
var fn = (y) => y - this.birth; // this.birth仍是1990
return fn.call({birth:2000}, year);
// 原本需要写作fn.call(this, {birth:2000}, year)
}
};
obj.getAge(2015); // 25