共计 14239 个字符,预计需要花费 36 分钟才能阅读完成。
前言
温故而知新, 可以为师矣. 相信大家都会有这种感觉, 很多学过的知识经常不使用就会慢慢遗忘!!! 本文把以前自己关于 ES6 的入门读书笔记重新汇总了一下, 并结合了工作中常用的使用场景 …
变量声明方式 let,const
ES5 中声明变量:
a. var 命令会发生”变量提升“现象,即变量可以在声明之前使用,值为 undefined。b. es5 中变量只有两种作用域: 全局 和 局部(函数内声明); 全局和局部都有变量提升现象; 先提前, 再进行赋值.
不合理场景 1: 局部内层变量 可能覆盖掉 全局变量
不合理场景 2: for 循环中 用 var 声明的 变量 i; 会泄露成全局变量, 循环结束并没有消失
ES6 中声明变量:
1. 声明的变量 a 的作用域为块级, 并且只在自己所在的块级作用域起作用; 外层作用域不能访问内层, 内层可以访问外层的;
2. 内 && 外层的同名变量互不干扰; 内层重新赋值也不会对外层造成影响;
3. 变量必须先声明, 再使用, 否则报错...(暂时性死区特性), 没有所谓的变量提升
4. 同一作用域不能重复声明同一个变量; 函数 function 第一层作用域变量声明不能和形参一样; 否则报错
// 注意:
1. es6 中, 变量在 for 循环中的使用
每一轮的 i 值 只在当前的循环中有效; 相当于每一次循环 i 都是一个新变量
// 1. 循环变量在设置的时候是: 一个父作用域
// 2. 循环体内部又是一个单独的子作用域
// 3. 所以当同时两个块级作用域如使用相同的变量 i, 循环体内部会使用自己作用域声明的 i
2.ES6 规定,块级作用域之中,函数声明语句的行为类似于 let,在块级作用域之外不可引用。// 1. 避免在块级作用域内使用函数时声明的方式 (function fn(){xxx}) 声明函数
// 2. 可以使用表达式方式 let f = function(){}
// 也就是外层无法调用内层声明的函数...
3.const 声明一个常量: 该变量不能变化, 是一个恒定值
const NUM_100 = 100; // 定义时就需要初始化
// const 实际上保证的并不是变量的值不得改动,而是变量指向的那个内存地址所保存的数据不得改动。// 值类型: 数据就 等同于 这个常量的地址的值
// 引用类型: 这个常量 是一直指向一个固定的地址, 不能变的(修改指向就保错, 即赋值操作); 只不过对象本身可变
变量的解构赋值语法
解构赋值, 我按照字面意思就是 解析数据结构, 然后给一一对应的变量进行赋值的一种语法
-
解构的语法:
= 号左边是: 匹配模式; = 号右边是: 实际的数据(或者数据对应的变量); 解构的结果: 解构成功: 左边变量的值 就是右边对应变量的值 解构不成功: 即没有对应值匹配, 变量的值变为 undefined 不完全解构: 左边的模式之匹配到右边数组的一部分
-
变量是复杂数据类型(数组, 对象)
1. 数组解构赋值 1. 右边的值需要能够被遍历 2. 允许左边给默认值: let [x=1, y=x] = ['xxxx']; 3. 支持嵌套结构的 解构赋值 注意: let [x, y=true] = ['xxxx']; // 右边数组对应成员要 === undefined // console.log(x,y); // 如果是 null, 则默认值不会生效; // 如果右边 不是 undefined, 则左边 会取到值 2. 对象的解构赋值 1. 对象本身就是无序的, 是根据左右同名变量 来做赋值操作, 匹配规则和数组类似 // 对象的解构赋值的内部机制,是先找到同名属性,然后再赋给对应的变量。真正被赋值的是后者 例: let {foo: foo, bar: bar} = {foo: "aaa", bar: "bbb"}; 2. 持嵌套结构的 解构赋值 let obj = {}; let arr = []; ({foo: obj.num, bool: arr[0]} = {foo: 123, bool: true}); // 圆括号 console.log(obj, arr); 3. 对象的解构赋值,可以很方便地将现有对象的方法,赋值到某个变量, 几个例子 3-1 let {sin, cos} = Math; // 将 math 对象中方法给对象 3-2 取出数组的首尾 2 项 let list = [1,2,323,123,12,2]; let {0: first, [list.length-1]: last} = list;
-
变量是简单数据类型(字符串, 数值, 布尔值)
1. 字符串的解构赋值 字符串被转换成了一个类似数组的对象: 可以理解未伪数组 let [a,b,c,d,e] = 'hello'; // 每个变量对应一个字符 2. 数值和布尔值的解构赋值 解构赋值的规则: 只要等号右边的值不是对象或数组,就先将其转为对象。由于 undefined 和 null 无法转为对象,所以对它们进行解构赋值,都会报错 所以, 数值和布尔值会先转成其包装对象 Number 和 Boolean 对象; 然后可以赋值对象的属性
-
函数参数的解构
1. 会将实参与形参一一对应 console.log([[1, 2], [3, 4]].map(([a, b]) => a + b));
-
常用的使用场景
变量之间值的交换; 函数中传参和接受返回值(对象的方式); 对象遍历等等... 1. 交换变量的值 let v100 = 100; let v1 = 1; [v1, v100] = [v100, v1]; console.log(v1, v100); 2. 接受函数的多个返回值: 比如数组, 对象 // 函数只能返回一个值,如果要返回多个值,只能将它们放在数组或对象里返回。// 有了解构赋值,取出这些值就非常方便。function example() {return [1, 2, 3]; } // let [a, b, c] = example(); 3. 函数传参 // 解构赋值可以方便地将一组参数与变量名对应起来 // 参数是一组有次序的值 function f([x, y, z]) { } f([1, 2, 3]); // 参数是一组无次序的值 function f({x, y, z}) { } f({z: 3, y: 2, x: 1}); 4.json 数据的处理 // 解构赋值对提取 JSON 对象中的数据,尤其有用。let jsonData = { id: 42, status: "OK", data: [867, 5309] }; let {id, status, data: arr1} = jsonData; console.log(id, status, arr1); 5. 设置函数参数的默认值 // 避免了在函数体内部再写 var foo = config.foo || 'default foo'; // 在传参时; 特别是传一个对象参数时, 可以事先配置好参数的默认值 // func({参数 1 = true, 参数 2 = false, ...} = {外部实参没有传值的就是用默认值}){} 6. 遍历 Map 结构 // 可迭代对象, 都可以用 for...of 来遍历 const map = new Map(); map.set('first', 'hello'); map.set('second', 'world'); for (let [key, value] of map) {console.log(key + "is" + value); } // 获取键名 for (let [key] of map) {console.log(key); } // 获取键值 for (let [,value] of map) {console.log(value); } 7. 模块导入 // 加载模块时,往往需要指定输入哪些方法。解构赋值使得输入语句非常清晰 // const {SourceMapConsumer, SourceNode} = require("source-map");
字符串, 数组, 对象的扩展
字符串方法
1. 处理 4 个字节存储的单个字符
// 测试一个字符由两个字节还是由四个字节组成的最简单方法 (Unicode 编号大于 0xFFFF)
// codePointAt(下标): 返回 10 机制字节码;
function is_32bit(char) {return char.codePointAt(0) > 0xFFFF;
}
console.log(is_32bit('????a')); // true
// 识别 4 个字节 (32 位) 组成的单个字符
console.log(String.fromCodePoint(0x20BB7)); // ????
2. 字符串的遍历 for of
let text = '我的名字';
for (const char of text) {console.log(char);
}
3. 确定一个字符串中是否包含另一个目标字符串
// includes(), startsWith(), endsWith() // 返回 true 和 false
console.log(text.startsWith('我'));
console.log(text.endsWith('我'));
console.log(text.includes('我'));
4.repeat(num); 将字符串重复 num 次并返回
console.log(text.repeat(3));
5. 字符串补全长度的功能
// padStart()用于头部补全,padEnd()用于尾部补全
// 参数 1: 补全后的生效长度; 参数 2: 用于补全的字符串(没有参数默认空格)
// 长度过了; 会截取超出位数的字符串
// 长度 <= 原长度; 返回自己
// 用途 1: 将数值补全为指定位数
console.log("1".padStart(10, '0')); // 0000000001
// 场景 2: 日期补全
console.log('09-12'.padStart(10, '2018-MM-DD')); // 2018-09-12
模板字符串
模板字符串: 反引号 ` 标识;
// 变量名使用 ${变量名}; 可以省去字符串的拼接了
let name = "bob";
let age = 24;
console.log(`Hello ${name}, how are you ${age}?`);
// ${这里面可以进行运算; 函数调用; 放对象的属性等}; 相当于执行 js 代码
// 还可以相互嵌套
当然, 模板字符串的用法比较复杂, 后续再深入总结
数值类型方法
// 1. 检查数字为有限值
Number.isFinite(12); // true; 其他类型都为 false
// 2. 检查数值是不是 NAN
Number.isNaN(1+NaN); // true; NaN 数值与非数值运算的结果 NaN
// 3.Number.parseFloat 和 Number.parseInt; 将 ES5 的全局方法移到 Number 对象上
// 4.Number.EPSILON * Math.pow(2, 2): 两个浮点数之间的最小误差;
// 差值小于它, 就可以认为时相等
// 5.Math 方法的扩展
console.log(Math.round(4.5)); // 5; 四舍五入
// Math.trunc 方法用于去除一个数 (正负都可以) 的小数部分,返回整数部分。console.log(Math.trunc(3.1));
// 兼容性写法
// Math.trunc = Math.trunc || function(x) {// return x < 0 ? Math.ceil(x) : Math.floor(x);
// };
// Math.sign()
// 判断正负, 还是 0; 对非数值, 能转化的转化; 不能转的就是 NaN
// 返回值: 正 +1; 负 -1; 0; -0; 其他值 NaN
数组的扩展方法
ES6 中会将数组空位转为 undefined
1.Array.from(param1, param2)方法用于将两类对象转为真正的数组:参数 1: 一个对象 ==> 伪数组对象和可遍历(iterable)的对象
参数 2: 回调函数 ==> 类似于数组的 map 方法,对每个元素进行处理,将处理后的值放入返回的数组。return 值: 一个数组;
示例:
let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
// 0: 'a',
// 1: 'b',
// 2: 'c',
// length: 3
};
let real_arr = Array.from(arrayLike);
2.Array.of(传一组数值); 用于将一组值,转换为数组。弥补了构造函数 Array()传数值的缺点
参数: 一组数值, 如: 1,2,3,4...
return 值: 一个数组
3. 实例方法
3.1 arr.find(): 类似过滤函数 filter(function(value, index, arr))
使用: 传入一个回调函数, 返回第一个符合要求的成员
示例: var res = [1,2,3,4,-100].find(n => n < 0); // -100
3.2 arr.findIndex(): 同上, 只不过是返回第一个符合条件的数组成员的位置
注意: 第二个参数是传一个对象,回调函数中若使用了 this, 则指向这个对象
3.3 arr.includes(): 判断数组中是否包含我们给定的值; 这样以后就不用 indexOf 了
3.4 实例数组的遍历方法: entries(),keys() 和 values() 用于遍历数组 返回一个遍历器对象
// keys()是对键名的遍历: 对应索引
// values()是对键值的遍历: 对应值
// entries()是对键值对的遍历: 索引 + 值
4. 数组扩展方法 [a, b, c]
map 映射, reduce 汇总, filter 过滤, forEach 迭代
1. map: 一个映射一个
// [100, 59, 22] => [及格, 不及格, 不及格]
let score = [100, 59, 22];
let res = score.map(item => item>60? '及格':'不及格');console.log(res);
2. reduce: 一堆变成一个
// temp 为中间结果; 如果不设置, 则为第一个下标为 0 的数
let res1 = score.reduce(function(temp, item, index, arr) {if (index != arr.length - 1) {return item + temp;} else {return (temp + item) / arr.length;
}
});
console.log(res1);
3.filter: 保留我想要的结果
let res2 = score.filter(item => item%11!=0);
console.log(res2);
4.forEach: 只是操作一下每一项; 返回值为 undefined
let arr = [1,2,3,4]
arr.forEach(function (item, index, arr) {
// 这里可以用外部变量接受 这里面操作的值
console.log(index +':'+ item);
});
console.log(res3); // undefined
对象的扩展
这里主要介绍一下对象的多种遍历方法; 其他内容在扩展运算符 … 中总结.
1.for...in
for...in 循环遍历对象自身的和继承的可枚举属性(不含 Symbol 属性)。2.Object.keys(obj),values(obj),entries(obj)
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含 Symbol 属性)的键名, 值, 键值对。3.Object.getOwnPropertyNames(obj)
返回一个数组,包含对象自身的所有属性(不含 Symbol 属性,但是包括不可枚举属性)的键名。4.Object.getOwnPropertySymbols(obj)
返回一个数组,包含对象自身的所有 Symbol 属性的键名。5.Reflect.ownKeys(obj)
返回一个数组,包含对象自身的所有键名,不管键名是 Symbol 或字符串,也不管是否可枚举。
扩展运算符 …
1. 扩展运算符是什么?
扩展运算符用三个点... 表示: 相当于函数 rest 参数的逆运算, 可以将数组, 对象中的成员序列化出来
我这里暂且把它理解为一种运算符吧, 用来解析各种数据类型的成员
2. 扩展运算符的使用场景?
2.1 将数组成员转为一个逗号分隔的参数序列:
这样调用一些数组的 API 时; 可以直接传一个...arr 进去, 省去了传参的麻烦
例 1: console.log(...[1,2,3]); // 1 2 3
例 2: var date = new Date(...[2015, 01, 01]);
console.log(date); // 2015-01-31T16:00:00.000Z
2.2 取代 apply 方法:
// ES5 的写法
let max1 = Math.max.apply(null, [14, 3, 77]);
// ES6 的写法
let max2 = Math.max(...[14, 3, 77]);
2.3 数组的深拷贝: 将对象全部拷贝一份, 是一个独立的内存空间
let arr1 = [0, 1], arr2 = [...arr1]; // 用变量去接受经过扩展运算符运算的数组
arr1[0] = 100; // 修改数组 arr1
console.log(arr1); // [100, 1] 发送改变
console.log(arr2); // [0, 1] 未改变
2.4 数组的合并
注意: 合并操作是浅拷贝: 是对数组中对象成员的引用
浅拷贝: (分为简单数据类型引用: 修改数据另一个不会变; 复杂数据类型引用: 修改后会改变)
arr3 = [...arr1, ...arr2]; // 此时 arr3 为一个新数组; [100, 1, 0, 1], 因为内部成员都是数值,
所以修改了 arr1 或者 arr2 中的元素也不会变
那么, 如果数组中成员是对象; 则会改变成员属性, 合并生成的数组成员也会变
const a1 = [{foo: 1}];
const a2 = [{bar: 2}];
const a3 = [...a1, ...a2];
console.log(a3); // [{ foo: 1}, {bar: 2} ]
a1[0].foo = 100;
console.log(a3); // [{ foo: 100}, {bar: 2} ]
2.5 可以和变量的解构赋值一起使用; 右边是对象也是可以的
let [first, second, ...rest] = [1,2,3,4,5,6];
console.log(first); // 1
console.log(second); // 2
console.log(rest); // [3,4,5,6]
2.6 还有与 Array.from()方法类似的作用, 将 类似数组的对象和可迭代对象 转为真数组
console.log([...'hello']); // ["h", "e", "l", "l", "o"]
注意: 如果涉及到操作四个字节的 Unicode 字符的函数; 可以使用[...string], ... 能够识别;
2.7 扩展运算符在对象中的使用
// 解构赋值, 如果右边数据是 undefined 或 null 则解构会失败
let {x, y, ...z} = {x: 1, y: 2, a: 3, b: 4}; // x,1; y,2; z,{a:3, b:4}
// 注意: 如果扩展运算符后面不是对象,则会自动将其转为对象。{...1}, {...true}, {...undefined}, {...null} 都会转为 空对象{}
函数扩展
函数参数设置默认值
语法: function(x= 默认值 x, y= 默认值 y); 当然也可以使用解构赋值, 使用对象的形式设置,({x=xxx, y=yyy})
默认值参数放在括号尾部
1. ES5 中设置默认值的方式
function fn1(x, y) {
y = y || "world"; // ES5 中, 在函数体内赋值一个默认值
console.log(x, y);
}
fn1('hello'); // hello world
fn1('hello', 'bob'); // hello bob
fn1('hello', ''); // 传空值时也使用默认值
fn1('hello', false); // 传 false 时也使用默认值
// ES6 中 直接给 () 中参数赋默认值, 相当于初始化形参, 函数体内不允许 let 和 const 再次声明
// ES6 中会事先对参数 y 进行类型判断: typeof y === 'undefined'; 是才给默认值
function fn2(x, y = 'ES6') {console.log(x, y);
}
fn2('learning'); //learning ES6
fn2('learning', ''); //learning 空也能输出
fn2('learning', false); //learning false 布尔值也可以
2. 构造函数中用来初始化 函数的属性 function Person(name='bob') {this.name = name};
也是可以直接在 () 中传默认值的
3. 解构赋值形式给函数传参
例 1:
function fn3({x, y = 100}) {
// 函数的形参接受一个对象; 函数传值也要传一个对象;
console.log(x, y);
};
// ES5 中我们是传一个对象, 然后再定义变量 保存 对象中对应的属性值
// ES6 可以直接在形参中 去接受对应的属性值
fn3({}); // undefined 100;
fn3(); // 保错
例 2:
// 下面我们重写一下, 注意::: 这种方式的传参是设置了对象解构赋值的默认值为空对象, 这样直接调用便不会报错
function fn4 ({x, y = 101} = {}) {
// 不传值的情况下: 给函数一个默认参数: 空对象
console.log(x, y);
};
fn4(); //undefined 101; 相当于 fn4({});
4. 默认参数的作用域
函数 () 中式一个单独的作用域, ES6 中函数体中的运算会先去 () 中找对应的变量进行运算
rest 参数
ES6 引入 rest 参数(形式为... 变量名),用于获取函数的多余参数,这样就不需要使用 arguments 对象了。rest 参数搭配的变量是一个数组,参数都放在这个数组中。要使用的话, 直接在函数体中遍历即可, 当然...rest 放在 () 尾部
举个栗子:
function add (...number) {
let sum = 0;
// number 变量相当于一个存放形参的数组
// 可以使用数组的方法, 也就是说, 我们可以当作数组来操作这个参数 number
// 基本方法 和 迭代方法都能使用
for (let num of number) {sum += num;}
return sum;
}
console.log(add(1,2,3,4,5)); // 15
箭头函数 () => {}
1. 箭头函数基本语法:
var 变量指向这个函数 = (参数 1, 参数 2...) => {函数体大于一行时用大括号}
理解: ES6 中箭头函数 相当于函数的简写, 省略了 function 关键字, 只有一个参数时还可以省略()
箭头左边是 (参数) => 箭头右边是函数体(一行代码可以省略大括号, 直接写返回值表达式)
// 如果返回的是一个对象则加括号({对象})
2. 常用的使用场景
2.1 回调函数的简化
// 比如数组常用的迭代方法 map: 常规方法是 传入一个回调函数 function(x) {return x**2};
var arr1 = [1,2,5,3,6,0];
var result1 = arr1.map(x => x**2);
// 排序
var result2 = arr1.sort((a, b) => a - b); // [0,1,2,3,5,6]
// 箭头函数传 rest 参数
let arr3 = (...numbers) => numbers; // 自动将参数序列转为数组
2.2 嵌套使用; 函数式编程
例如: 要实现将一个值 插入到数组 某个值的后面, 然后返回一个新数组
function insert (value) {return {into: function (array) {return {after: function (after_value) {
// 起始位, 要删除的项, 替换项
array.splice(array.indexOf(after_value) + 1, 0, value);
return array;
}}
}}
}
// 用箭头函数实现; 简化了很多
// 声明一个变量指向函数; 不要忘记对象用 () 包起来
var insert = (value) => ({into: (array) => ({after: (after_value) => {array.splice(array.indexOf(after_value) + 1, 0, value);
return array;
}})});
var res = insert(100).into([1, 2, 3]).after(2);
console.log(res); // [1, 2, 100, 3]
3. 箭头函数注意事项;
1.this 对象 ==> 指向定义时的对象, 而不是谁调用就指向谁了; 相当于固定了 this 指向
箭头函数根本没有自己的 this,导致内部的 this 就是外层代码块的 this
箭头函数中的 this 相当于 ES5 中 引用了外层函数的 this; 在外层函数用 var _this = this; 然后在箭头函数中使用
2. 箭头函数不能当作构造函数, 不能使用 new 去声明
3. 没有 arguments 对象了, 使用 rest 参数替代
4. 不能使用 yield, 不可以作为生成器函数
函数的尾调用
函数的尾调用优化
function f(x){return g(x);
// 函数 f 的最后一步是 调用函数 g,这就叫尾调用。}
function f(x){g(x);
// 函数没有明确返回值, 默认回返回 undefined; 所以不是尾调用
return undefined;
}
优化思路: 用内层函数的调用帧,取代外层函数的调用帧(保存了函数调用后的信息)
相当于可以不用调用外层函数
注意:
只有不再用到外层函数的内部变量,内层函数的调用帧才会取代外层函数的调用帧,否则就无法进行“尾调用优化”。尾递归优化
思路: 把所有用到的内部变量改写成函数的参数
1. 参数设置成默认值的方式;
2. 函数柯里化 currying; 意思是将多参数的函数转换成单参数的形式
function Fibonacci (n , ac1 = 1 , ac2 = 1) {if( n <= 1) {return ac2};
// 尾部调用自身; 并且参数中保存了上一次调用帧; 节省内存
return Fibonacci (n - 1, ac2, ac1 + ac2);
}
console.log(Fibonacci(100));
// 注意:
// ES6 的尾调用优化只在严格模式下开启,正常模式是无效的。
Set 和 Map 数据结构
set
Set 数据结构: 可以理解为没有重复成员的一个类似数组的对象; 就叫集合吧
结构形式: {1, 2, 3, 4}
使用方法:
// 使用构造函数 Set; 参数为一个可遍历的对象
const set = new Set([1,2,3,4]); // 实例化一个 set; set 结构是可迭代的对象
// 返沪值: {1, 2, 3, 4}
Set 的属性和方法
1. size: 返回 set 集合的大小, 即成员个数
2. Set 的增删查
// add(value):添加某个值,返回 Set 结构本身。// delete(value):删除某个值,返回一个布尔值,表示删除是否成功。// has(value):返回一个布尔值,表示该值是否为 Set 的成员。// clear():清除所有成员,没有返回值。3. Set 遍历成员; Set 的遍历顺序就是插入顺序。// keys():返回键名的遍历器
// values():返回键值的遍历器
// entries():返回键值对的遍历器
// forEach():使用回调函数遍历每个成员, 回调参数为键值和 set 自身
使用场景:
Set 作为一种数据结构, 主要用来存放数据, 并且内部成员不重复; 我们可以利用它的这个特性来做一些事.
1. 比如去重
let arr = [1,2,2,3,1,1,14];
let str = 'dsadaedwdwa';
console.log([...new Set(arr)]);
console.log([...new Set(str)].join());
Map
其实 Map 有点类似 python 中的字典结构;
ES6 中 Map 类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
也就是说,Object 结构提供了“字符串: 值”的对应,Map 结构提供了“值 => 值”的对应
结构形式: Map: {[ 1, 2, 3] => ‘ 数组 ’, ‘name’ => {name: ‘bob’} }
使用方法:
使用构造函数 Map 进行实例化; 参数为双元素的可迭代对象(能够调用 next 方法的对象)
const newMap = new Map([['name', 'Blob'], ['age', 24]]);
// 也可实例化一个空 map 对象, 通过 set(值 1, 值 2)方法去添加成员
Map 的属性和方法: 基本与上面的 Set 一致
1.Map 的增删查
// set(key1, value1):添加一个键值对
// get(key); 获取某个键值对
// delete(key):删除某个键值对
// has(key):返回一个布尔值,表示该值是否为 Map 的成员。// clear():清除所有成员,没有返回值。
常用场景:
可以使用扩展运算符...Map 可以实现与数组, 对象,json 对象的互转;
我们定义固定格式的数据时可以使用, 也可以用来简化判断语句
# set 中来判断 code
const NEED_LOGIN_CODE_SET = new Set([10007,100011])
if (NEED_LOGIN_CODE_SET.has(code)) { }
# map 取值
let buildEnv = process.env.VUE_APP_ENV
const K_V = [['development', 'address1'],
['test', 'address2'],
['production', 'address3']
]
const URL_MAP = new Map(K_V)
export default URL_MAP.get(buildEnv)
for…of
for…of 是 ES6 新增的语法; 用来遍历具有 Iterator 接口的对象; 这种对象有 next()方法,\
可以对自身进行遍历, 每一次调用便返回对应的值 …
for…of 循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如 arguments 对象、DOM NodeList 对象)、Generator 对象,以及字符串。
class 关键字: 类
-
ES5 中的类实现
// ES5 中对象实例化的方法: 通过构造函数实例化
function Func(x, y) { this.x = x; this.y = y; } // 给构造函数的原型添加属性 Func.prototype.toString = function() { // 把对象转为字符串 return '(' + this.x + ',' + this.y + ')'; } // 实例化一个对象 var f = new Func(1,100); console.log(f.toString());
-
ES6 的类实现
// ES6 中 通 class 来定义类; 其实就是构造函数的改写, 是 js 的语法更像后台语言 class Func1 { // 构造实例对象的方法; 相当于初始化 constructor(x, y) { this.x = x; this.y = y; } // 添加类方法: toString()方法 toString() {return '(' + this.x + ',' + this.y + ')'; } } // 类: 就是一个函数, 本身为一个构造函数; 也是通过 new 来实例化一个对象 console.log(typeof Func1); console.log(Func1 === Func1.prototype.constructor); let f1 = new Func1(); console.log(f1.__proto__.constructor); // 省略了__proto__ // 类的方法都定义在 prototype 对象上
-
ES6 中的继承
// ES6 面向对象写法: class 替换 构造函数 class User { // 构造器, 初始化 constructor(name, pass) { this.name = name; this.pass = pass; } // 添加方法和属性 showName() {console.log(this.name); } showPass() {console.log(this.pass); } } // 在继承 和 封装上的优势; 扩展性强...; 不用从 0 开始;; 可以使用前人造好的轮子 // 继承超类的属性和方法 class VipUser extends User { // 子类的初始化 constructor(level, ...args) {// 相当于调用父类的 constructor(name, pass) super(...args); // super 作为函数调用时,代表父类的构造函数 // super 作为对象时,在普通方法中,指向父类的原型对象;在静态方法中,指向父类。this.level = level; } // 方法 showLevel() {console.log(this.level); } } let vip = new VipUser(77, 'huhua', '123'); // 实例化 vip.showLevel(); vip.showName(); vip.showPass(); // 面向对象中类的应用实例 // 比如一个组件: 就是一个 class 继承一个组件 // JSX: == babel; browser.js
json 简写模式
// 1.JSON 对象: 两个方法
let json = {"name": '哈哈', "sex": "女"}; // json 对象键值必须是双引号
let str1 = 'http://www.baidu.com?data=' + encodeURIComponent(JSON.stringify(json)) ; // JSON 对象转为 json 字符串
console.log(str1);
let str2 = JSON.parse('{"a": 12,"b":"hello world"}');
console.log(str2); // JSON 字符串 转为 对象
console.log(str2.a);
// 2.JSON 简写
// 简写: 如果 key 值和 value 是一样的; 直接写一个就可以了...
// 可以省略一个 funcion; 即 success: function(obj) {} ==> 可以写成 success(obj){}
模块化加载方式
这里说两种常用的模块加载方式
- commonJS 模块
CommonJS 模块就是对象,输入时必须查找对象属性
导出:
module.exports = {m1: 'xxx', m2: function(){}}
导入:
const {m1, m2} = require('模块名')
模块输出的是一个值的拷贝: 如果输出一个值,模块内部的变化就影响不到这个值
模块是运行时加载(整个对象全部加载)
- ES6 模块化
export 导出模块:
默认导出:export default Person(导入时可任意命名)
单独导出:export const name = 'xxoo'
按需导出:export {age, name, sex} 前提是得先定义好
改名导出:export {name as newName}
import 导入模块:默认导入:import Person from "person"
整体导入:import * as Person from "person"
按需导入:import {age, name, sex} from "person"
改名导入:import {name as newName} from "person"
自执行导入:import "person"
复合导入:import Person, {name} from "person"
ES6 模块是编译时输出接口(按需导入)
ES6 模块输出的是值的引用, 即动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块
如果原始模块的变量变化, 就会影响引入了这个变量的模块中的值
未完待续 …