ES6知识点划分

1,解构赋值

let [head, ...tail] = [1, 2, 3, 4];
console.log(head) //1
console.log(tail) //[2, 3, 4]
let [x, y, ...z] = ['a'];
console.log(y) //undefined
console.log(z) //[]
let [a, [b], d] = [1, [2, 3], 4];
a // 1
b // 2
d // 4

let [er, tr, gr,yr] = [ 2,2,5, 1].sort();
 console.log(tr)//2
let [x1, y1 = 'b'] = ['a', undefined];
 console.log(y1);//b
 let [x = 1] = [null];
x // null
            let { foo: baz,bar:jjjfd } = { foo: 'aaa', bar: 'bbb' };
            log(baz);//aaa
            log(jjjfd);//bbb
            const node = {
  loc: {
    start: {
      line: 1,
      column: 5
    }
  }
};

let { loc, loc: { start }, loc: { start: { line }} } = node;
line // 1
loc  // Object {start: Object}
start // Object {line: 1, column: 5}

var {x: y = 3} = {x: 5};
y // 5

let {length : len} = 'hello';
len // 5
 let apss  = [[1, 2], [3, 4]].map(([a, b]) => a + b);
 log(apss);// [3,7]  map重新返回新的数组,
 

字符串的方法 // String.fromCodePoint

dePoint()方法,可以识别大于0xFFFF的字符
// let text = String.fromCodePoint(0x20BB7);
let text = 'fdsa放大发';
// for...of //为遍历字符串的方法
for (let i of text) {
  log(i); // 分别输出 fdsa放大发
}
// 单行
// `In JavaScript '\n' is a line-feed.`

// 多行字符串
// `In JavaScript this is
//  not legal.`

// 字符串中嵌入变量
let name = "Bob", time = "today";
log(`Hello ${name}, 
how are you ${time}?`);//Hello Bob, 
                        //how are you today?
 // 大括号内部可以放入任意的 JavaScript 表达式,可以进行运算,以及引用对象属性。
let x232 = 1;
let y2323 = 2;
log(`${x232} + ${y2323 * 2} = ${x232 + y2323 * 2}`)//1 + 4 = 5
function fn() {
  return "Hello World";
}

log(`foo ${fn()} bar`)//foo Hello World bar

let s = 'Helloworld!';

// log(s.startsWith('Hello'))// true返回布尔值,表示是否找到了参数字符串。
// s.endsWith('!') // true 返回布尔值,表示参数字符串是否在原字符串的头部。
// s.includes('o') // true 返回布尔值,表示参数字符串是否在原字符串的尾部

'hello'.repeat(2) // "hellohello" repeat方法返回一个新字符串,表示将原字符串重复n次

// 如果某个字符串不够指定长度,会在头部或尾部补全。padStart()用于头部补全,padEnd()用于尾部补全。
'x'.padStart(5, 'ab') // 'ababx'
'x'.padStart(4, 'ab') // 'abax'

// ES2021 引入了replaceAll()方法,可以一次性替换所有匹配。目前浏览器不适配 重写replaceAll方法
String.prototype.replaceAll = function(s1,s2){
return this.replace(new RegExp(s1,"gm"),s2);
}
log('aabbcc'.replaceAll('b', '_'));//aa__cc

数值的扩展

// ES5的写法
parseInt('12.34') // 12
parseFloat('123.45#') // 123.45

// ES6的写法
Number.parseInt('12.34') // 12
Number.parseFloat('123.45#') // 123.45

Number.isInteger();//用来判断一个数值是否为整数。

Math.trunc();//方法用于去除一个数的小数部分,返回整数部分。
log(Math.trunc('123.456') );//123

// Math.sign方法用来判断一个数到底是正数、负数、还是零。对于非数值,会先将其转换为数值。

// 它会返回五种值。

// 参数为正数,返回+1;
// 参数为负数,返回-1;
// 参数为 0,返回0;
// 参数为-0,返回-0;
// 其他值,返回NaN。
Math.sign(-5) // -1
Math.sign(5) // +1
Math.sign(0) // +0
Math.sign(-0) // -0
Math.sign(NaN) // NaN

// 新增了一个指数运算符(**) 
// 这个运算符的一个特点是右结合,而不是常见的左结合。多个指数运算符连用时,是从最右边开始计算的。
log(2 ** 3 ** 2)//512

函数的扩展

// 写法一
function m1({x = 0, y = 0} = {}) {
  return [x, y];
}

// 写法二
function m2({x, y} = { x: 0, y: 0 }) {
  return [x, y];
}



// 函数没有参数的情况
m1() // [0, 0]
m2() // [0, 0]

// x 和 y 都有值的情况
m1({x: 3, y: 8}) // [3, 8]
m2({x: 3, y: 8}) // [3, 8]

// x 有值,y 无值的情况
m1({x: 3}) // [3, 0]
m2({x: 3}) // [3, undefined];//不传y值类似于没有设置y这个变量

// x 和 y 都无值的情况
m1({}) // [0, 0];
m2({}) // [undefined, undefined]

m1({z: 3}) // [0, 0]
m2({z: 3}) // [undefined, undefined]


// 函数的length属性:该函数预期传入的参数个数。某个参数指定默认值以后,预期传入的参数个数就不包括这个参数了。同理,后文的 rest 参数也不会计入length属性。
// 如果设置了默认值的参数不是尾参数,那么length属性也不再计入后面的参数了
log((function (ty = 0, bf, cfd) {}).length) 
log((function (adf, bdd = 1, crr) {}).length) 

// rest参数的写法
// rest 参数(形式为...变量名),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
const sortNumbers = (...numbers) => numbers.sort();
// log(sortNumbers(3,5,5,46))


// 数组排序的简单方法 
// sort():简单的排序,只判断字符串的第一位数字; sort(value):value可以传true或者false,true在前,false在后

let values = [3,89,30,5];
var result = values.sort((a, b) => a - b);

数组的扩展

// ES5 的写法
// function f(x, y, z) {
//   // ...
// }
// var args = [0, 1, 2];
// f.apply(null, args);

// ES6的写法
function f(x, y, z) {
  // log(x,y,z)
}
let args = [0, 1, 2];
f(...args);

// ES6 的写法
let arr1 = [0, 1, 2];
let arr2 = [3, 4, 5];
arr1.push(...arr2);

const a1 = [1, 2];
// 写法一
const a2 = [...a1];
// 写法二
const [...a2] = a1;
// log(a2)

[...'hello']
// [ "h", "e", "l", "l", "o" ]

// Array.from方法用于将两类对象转为真正的数组
let arrayLike = {
    '0': 'a',
    '1': 'b',
    '2': 'c',
    length: 3
};
let arr2989 = Array.from(arrayLike);
// log(arr2989);

Array.from([1, , 2, , 3], (n) => n || 0)
// [1, 0, 2, 0, 3]

// 数组实例的copyWithin()方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
// target(必需):从该位置开始替换数据。如果为负值,表示倒数。
// start(可选):从该位置开始读取数据,默认为 0。如果为负值,表示从末尾开始计算。
// end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示从末尾开始计算。
// 这三个参数都应该是数值,如果不是,会自动转为数值
[1, 2, 3, 4, 5].copyWithin(0, 3, 4)
// [4, 2, 3, 4, 5]

[1, 2, 3, 4, 5].copyWithin(0, -2, -1)
// [4, 2, 3, 4, 5]

// 数组实例的 find() 和 findIndex()
// 数组实例的find方法,用于找出第一个符合条件的数组成员
log([1, 4, -5, 10].find((n) => n < 0))
// 上面代码中,find方法的回调函数可以接受三个参数,依次为当前的值、当前的位置和原数组。

// fill方法使用给定值,填充一个数组。
// fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。
log(['a', 'b', 'c'].fill(7, 1, 2))
// ['a', 7, 'c']

***// —entries(),keys()和values()——用于遍历数组 唯一的区别是keys()是对键名的遍历、values()是对键值的遍历***,entries()是对键值对的遍历。

for (let index of ['a', 'b'].keys()) {
  // console.log(index);
}
// 0
// 1

for (let elem of ['a', 'b'].values()) {
  // console.log(elem);
}
// 'a'
// 'b'

for (let [index, elem] of ['a', 'b'].entries()) {
  // console.log(index, elem);
}
// 0 "a"
// 1 "b"

let letter = ['a', 'b', 'c'];
let entries = letter.entries();
// console.log(entries.next().value); // [0, 'a']
// console.log(entries.next().value); // [1, 'b']
// console.log(entries.next().value); // [2, 'c']

// Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似, 该方法的第二个参数表示搜索的起始位置
//  log([1, 2, 3].includes(3, 3));//false
//  log([1, 2, 3].includes(3, -1));//true

// flat()默认只会“拉平”一层,如果想要“拉平”多层的嵌套数组,可以将flat()方法的参数写成一个整数,表示想要拉平的层数,默认为1。
// log([1, 2, [3, [4, 5]]].flat()); [1, 2, 3, [4, 5]]

// log([1, 2, [3, [4, 5]]].flat(2));// [1, 2, 3, 4, 5]



// flatMap()方法对原数组的每个成员执行一个函数(相当于执行Array.prototype.map()),然后对返回值组成的数组执行flat()方法。该方法返回一个新数组,不改变原数组。

// 相当于 [[2, 4], [3, 6], [4, 8]].flat()
[2, 3, 4].flatMap((x) => [x, x * 2]);// [2, 4, 3, 6, 4, 8]


// 相当于 [[[2]], [[4]], [[6]], [[8]]].flat()
[1, 2, 3, 4].flatMap(x => [[x * 2]]);// [[2], [4], [6], [8]]

const arr = [
  'peach',
  'straw',
  'apple',
  'spork'
];

const stableSorting = (s1, s2) => {
  if (s1[0] < s2[0]) return -1;
  return 1;
};

arr.sort(stableSorting)
// ["apple", "peach", "straw", "spork"]

对象的扩展

// JavaScript 属性名表达式 定义对象的属性,有两种方法。
// obj.foo = true;

// // 方法二
// obj['a' + 'bc'] = 123;

// 表达式还可以用于定义方法名。
let obj = {
  ['h' + 'ello']() {
    return 'hi';
  }
};

log(obj.hello()); // hi

// super关键字 我们知道,this关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super,指向当前对象的原型对象。
const proto = {
  foo: 'hello'
};

const obj323 = {
  foo: 'world',
  find() {
    return super.foo;
  }
};
// Object.setPrototypeOf(),为现有对象设置原型,返回一个新对象 
// 接收两个参数:第一个是现有对象,第二是原型对象。 
// 2、new 命令通过构造函数新建对象实例的过程,其本质是将实例的原型,指向了构造函数的prototype属性,然后在实例上执行构造函数。
Object.setPrototypeOf(obj323, proto);
log(obj323.find()) // "hello"

// // 因此 ES2020 引入了“链判断运算符”(optional chaining operator)?.,简化上面的写法。
// const firstName = message?.body?.user?.firstName || 'default';
// const fooValue = myForm.querySelector('input[name=foo]')?.value
// // 上面代码使用了?.运算符,直接在链式调用的时候判断,左侧的对象是否为null或undefined。如果是的,就不再往下运算,而是返回undefined。
// a?.b
// // 等同于
// a == null ? undefined : a.b

// a?.[x]
// // 等同于
// a == null ? undefined : a[x]

// a?.b()
// // 等同于
// a == null ? undefined : a.b()

// a?.()
// // 等同于
// a == null ? undefined : a()


// ES6 提出“Same-value equality”(同值相等)算法,用来解决这个问题。Object.is就是部署这个算法的新方法。它用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。

Object.is('foo', 'foo')
// true
Object.is({}, {})
// false

// Object.assign()方法用于对象的合并,将源对象(source)的所有可枚举属性
const target = { a: 1, b: 1 };

const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
log(target) // {a:1, b:2, c:3}

Symbol

let s1 = Symbol()
	
	// 或者,你也可以在调用Symbol()函数时传入一个可选的字符串参数,相当于给你创建的Symbol实例一个描述信息:
	let s2 = Symbol('another symbol')

	// 由于Symbol是一种基础数据类型,所以当我们使用typeof去检查它的类型的时候,它会返回一个属于自己的类型symbol,而不是什么string、object之类的:
	typeof s1  // 'symbol'
	
	// 另外 每个Symbol实例都是唯一的 ,所以当你比较两个Symbol实例的时候,将总会返回false:
	const a=Symbol("name");
    const b=Symbol("name");
    console.log(a===b) //false

    const name=Symbol();
    const age=Symbol();
    let obj={
         [name]:"已经代码"
    }
    obj[age]=18;
    console.log(obj[name]);//已经代码
    console.log(obj[age]);//18

  // 并且 当使用了Symbol作为对象的属性key后不能使用枚举方法
    const name=Symbol();
    const age=Symbol();
    const obj={
        [name]:"大师",
        [age]:16,
        sex:"男"
    }
    console.log(obj)
    console.log(Object.keys(obj));//["sex"]  使用symbol定义的属性,不能使用枚举遍历
    for(let p in obj){
        console.log(p); // sex
    }
    // 使用Object的API
    console.log(Object.getOwnPropertyNames(obj));// ["sex"] 得到符号类型代替的属性名,并且为数组

    console.log(Object.getOwnPropertySymbols(obj));// [Symbol(), Symbol()]
    const sybs=Object.getOwnPropertySymbols(obj);
    console.log(sybs[0]===name) //true 引用会相等
    
    //补充:
	// 1.Object.getOwnPropertyNames()方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括Symbol值作为名称的属性)组成的数组。
  // 2.Object.getOwnPropertySymbols()方法返回一个给定对象自身的所有 Symbol 属性的数组。
  
  // ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。set可以说是去重的方法
  // 例一
  const set = new Set([1, 2, 3, 4, 4]);
  log([...set]);// [1, 2, 3, 4]

  // Array.from方法可以将 Set 结构转为数组。
  const items = new Set([1, 2, 3, 4, 5]);
  const array = Array.from(items);

  function dedupe(array) {
  return Array.from(new Set(array));
}

dedupe([1, 1, 2, 3]) // [1, 2, 3]

// Map:Object 结构提供了“字符串—值”的对应,Map 结构提供了“值—值”的对应,是一种更完善的 Hash 结构实现。如果你需要“键值对”的数据结构,Map 比 Object 更合适。

const m = new Map();
const o = {p: 'Hello World'};

m.set(o, 'content')
log(m.get(o));// "content"
m.has(o) // true
m.delete(o) // true
m.has(o) // false

const map = new Map();

const k1 = ['a'];
const k2 = ['a'];

map
.set(k1, 111)
.set(k2, 222);

map.get(k1) // 111
map.get(k2) // 222


// 扩展运算符与其他结构数据转换
// 1:对象转数组 Map 转为数组
const myMap = new Map()
  .set(true, 7)
  .set({foo: 3}, ['abc']);
[...myMap]

_____________________________________________________________________________________

// ES6 关键字class、constructor、extends、static简介
// 先来看下传统ES5的写法.
// ES5写法

function StdInfo() {
		this.name = "cat";
		this.age = 30;
	}
 
	StdInfo.prototype.getNames = function () {
		console.log("name:" + this.name);
	}
	//得到一个学员信息的对象
	var p = new StdInfo()
	p.getNames()

// 一、class 使用
// 实质:
// 在类的实例中调用方法,其实就是调用原型上的方法。P = new Parent() P.constructor === Parent.prototype.constructor
// 注意:
// 1、定义类不存在变量提升,只能先定义类后使用,跟函数声明有区别的。
// 2、 定义在类中的方法不需要添加function
// 3、函数的定义方式有函数声明和函数表达式两种,类的定义方式也有两种,分别是:类声明和类表达式。
// 4、表达式申明时候,class关键字之后的类名可有可无,如果存在,则只能在类内部使用
// 5、方法之间不需要加逗号,否则会报错
// 6、类必须使用new调用,否则会报错 (ES5 中可以直接调用)
// 7、动态添加方法

Object.assign(Parent.prototype, {
	  getName() {
		  console.log('覆盖原来定义的')
	  }
})
 // 表达式:
 const People = class StdInfo {
		    constructor(){
				console.log(StdInfo);  
			   // 这里可以打印出值,是一个函数
			}
			getName () { // 不需要添加function
 
		    }
}
// 	声明:
class StdInfo { }	

// 二、constructor
// 意义:类初始化时候执行的函数
// 作用:初始化属性, 传入所需要的参数
// 返回值:自动返回实例对象
// 注意点:1、可以省略constructor ,一个类中只能有一个constructor函数,定义多个会报错
// 2、继承时候super() 需要写在constructor里面调用,然后才能使用this

class Parent {
	 constructor(name, age) {
		super(name, age) //初始化属性
		this.name = name // super 之前会报错, 应该写在super 之后
	}
}

// 三、继承 extends
// 和ES5原理对比:、继承 extends ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this) )。
// ES6 的继承机制完全不同,实质是先将父类实例对象的属性和方法,加到this上面(所以必须先调用super方法),然后再用子类的构造函数修改this。
// 注意点:1、如果子类中有constructor构造函数,则必须使用调用super。且把父级的参数继承下来
// 2、子类必须在constructor方法中调用super方法,否则新建实例时会报错(this is not defined)
// 这是因为子类没有自己的this对象,而是继承父类的this对象。如果不调用super方法,子类就得不到this对象。

class Parent {
		constructor(name, age) {
				this.name = name;
				this.age = age;
		}
		getName() {
				console.log(this.name)
		}
}
class Child extends Parent {
		constructor(name, age) {
				super(name, age) //代表父类的构造函数
				this.name = name // super 之前会报错, 应该写在super 之后
		}
}

// 四、static 的使用
// 解释:类其实就是实例的原型, 所有在类中定义的方法, 都会被实例继承,在new 一个实例后就可以直接使用类中的方法。
// 如果在一个方法前, 加上static关键字,
// 就表示这个方法不会被实例继承, 而是直接通过类来调用,及 “类名”+ ‘.’ + “方法名” , 这就称为“ 静态方法”。
// 作用: 写工具 函数
// 使用
// 1、类中通过类名 直接调用 不能在实例后调用实例的方法。

class StuInfo {
		static staticMethodsParent() {
		  console.log('static 使用1 from 父类');
		}
}
StuInfo.staticMethodsParent()

// 2、子类可以调用父类的静态方法

class Parent {
		static staticMethodsParent() {
		  console.log('static 使用1 from 父类');
		}
}
class Child extends Parent {
        constructor() {
            super() // 不管是否有这个super,子类都可以获取到父类的静态方法
        }
		static staticMethodsChild() {
			console.log('static 使用2 from 子类');
		}
}
 
Child.staticMethodsChild() // static 使用2 from 子类'
Child.staticMethodsParent() // static 使用1 from 父类

// 3、 通过关键字this 使用 static 定义的方法

class StuInfo{
		constructor () {
				this.constructor.getStaticMethodsName()
		}
		static staticMethodsParent() {
				console.log('static 使用3 from 父类');
		}
}
StuInfo.staticMethodsParent()

// 4、 通过this 使用static 的第二种情况 ,在一个静态方法中 使用另一个静态方法

class StuInfo {
			static staticMethodsParent1() {
				return "第一个静态方法返回值"
			}
			static staticMethodsParent2() {
			   console.log('第二个静态方法执行得到的结果:' + this.staticMethodsParent1())
			}
}
StuInfo.staticMethodsParent2()

// 5、通过super 调用父级的 静态方法

class Parent {
			static staticMethodsParent() {
				console.log('父级的 static ');
			}
	}
 
	class Child extends Parent {
			constructor () {
				super()
			}
			static staticMethodsChild() {
				console.log( super.staticMethodsParent())
			}
	}	
   Child.staticMethodsChild()

// prototype 继承
// 所有的 JavaScript 对象都会从一个 prototype(原型对象)中继承属性和方法:
// Date 对象从 Date.prototype 继承。
// Array 对象从 Array.prototype 继承。
// Person 对象从 Person.prototype 继承。
// 所有 JavaScript 中的对象都是位于原型链顶端的 Object 的实例。
// JavaScript 对象有一个指向一个原型对象的链。当试图访问一个对象的属性时,它不仅仅在该对象上搜寻,还会搜寻该对象的原型,以及该对象的原型的原型,依次层层向上搜索,直到找到一个名字匹配的属性或到达原型链的末尾。
// Date 对象, Array 对象, 以及 Person 对象从 Object.prototype 继承。
// 添加属性和方法
// 有的时候我们想要在所有已经存在的对象添加新的属性或方法。
// 另外,有时候我们想要在对象的构造函数中添加属性或方法。
// 使用 prototype 属性就可以给对象的构造函数添加新的属性:

function Personfds(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}
// 当然我们也可以使用 prototype 属性就可以给对象的构造函数添加新的方法:
Personfds.prototype.nationality = "English";

function Person(first, last, age, eyecolor) {
  this.firstName = first;
  this.lastName = last;
  this.age = age;
  this.eyeColor = eyecolor;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值