前言
温故而知新,可以为师矣. 相信大家都会有这种感觉,很多学过的知识经常不使用就会慢慢遗忘!!!本文把以前自己关于 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 模块输出的是值的引用, 即动态引用,并且不会缓存值,模块里面的变量绑定其所在的模块
如果原始模块的变量变化,就会影响引入了这个变量的模块中的值
未完待续...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。