一、class
语法:class是构造函数的语法糖
class Cat { constructor(name) { // 本身方法 this.name = name; }; run() { // 原型方法 console.log(this.name + "running") }; }; let cat1 = new Cat("小花"); console.log(cat1);
- 注意不需要return,如果是基本类型值不会输出,如果是引用类型改变;
- constructor和 方法都是在原型上面;
- 了解:class 有一个getter函数和setter函数:
class Cat { get name() { return "小黑"; }; set name(val) { console.log(val); }; }; let cat1 = new Cat(); console.log(cat1); cat1.name = "hello";
注: 不使用constructor可以省略不写;
静态和实例(成员):
实例方法和实例属性(成员方法和属性)必须通过用实例化进行调用;
静态属性和方法:通过类进行调用;
1.继承:
1)语法: extends关键字
class Parent { constructor(name) { this.name = name; }; fn() { console.log("fn"); }; };
class children extends Parent {
// 默认省略可以省略constructor
constructor(x, color) {
super(x) ; // 调用父类的constructor方法
this.color = color;
};
};
let c1 = new children("小花");
console.log(c1);
c1.fn();
2)手动在子类添加constructor,必须在construtor写super();
3)Super 方法和属性:
Super方法:调用父类的constructor方法;
Super属性:在子类里面,调用父类的属性和方法;
二、iterator:
- 概念:在集合的数据结构中,数组,对象,set,map 需要统一接口,来进行处理。Iterator就是这个机制,为不同的数据结构提供统一的接口,任何的数据结构,只要部署了iterator就可以进行循环遍历。
- 作用:1.提供统一接口,2.按照一定的顺序循环遍历,3.为for...of...提供消费
- 目的:提供统一接口
- 模拟iterator接口:
let arr = ["a", "b", "c"]; function myIterator(arr) { let index = 0; return { next() { // if (index < arr.length) { // return { // value: arr[index++], // done: false // } // } else { // return { // value: undefined, // done: true // } // }; return index < arr.length ? { value: arr[index++], done: false } : { value: undefined, done: true }; }; }; }; let x = myIterator(arr); console.log(x.next()); // {value: "a", done: false} console.log(x.next()); // {value: "b", done: false} console.log(x.next()); // {value: "c", done: false} console.log(x.next()) ; // {value: undifined, done: true}
1.创建的是一个指针对象,指向当前数据结构的起始位置
2.第一次调用next指向的是第一个位置的元素
3.第二次调用next指向的是第二个位置的元素
4.一直指向到结束位置;
注意:done为false表示可以继续循环遍历,done为true表示循环遍历结束;
5.默认的 Iterator 接口部署在数据结构的Symbol.iterator属性;
obj[Symbol.iterator] = function() { let index = 0; return { next: () => { // console.log(Object.keys(this).length) // console.log(Object.keys(this)[index]) // 取属性 // console.log(this) //对象 // console.log(this[Object.keys(this)[index]]) // 取值 if (index < Object.keys(this).length) { return { value: this[Object.keys(this)[index++]], done: false } } else { return { value: undefined, done: true } } } } }
三、Generator
1.概念:
解决异步编程方法;
是一个状态机,可以从函数的内部返回多个状态
返回的是一个iterator对象
2.语法
1) 在function和函数名中间写一个*
2) 返回的是一个iterator对象,通过调用next()来获取值
3) 通过yield可以在函数的外部返回多个状态,状态机
4) 因为返回的是一个iterator对象,所以可以使用for...of...
5) 注意:可以使用return,但是return返回done:true;表示循环遍历已经结束;
for...of...循环是拿不到return后面的值;
6) Yield有阻塞代码执行,必须调用next方法之后,才可以执行;
function * fn(){ console.log(fn()); let aa = 8; console.log(aa); yield 'hello'; yield 2 + 1; let a = yield 4; // let b; console.log(a); let b = yield 12; return b; } let g = fn(); console.log(g.next()); // fn {<suspended>} 8 {value: "hello", done: false} console.log(g.next()); // {value: 3, done: false} console.log(g.next()); // {value: 4, done: false} console.log(g.next(9)); // 9 {value: 12, done: false} console.log(g.next(10)); // {value: 10, done: true}
四、扩展内容:
1. 对象的扩展
let obj = { a: 1, b: 2 }; console.log(Object.getOwnPropertyDescriptor(obj, "a")); // {value: 1, writable: true, enumerable: true, configurable: true} Object.defineProperty(obj,'a',{ // value: 'hello', writable : false, // 是否可修改值 enumerable: false, //是否可遍历 configurable: false // 是否可设置 }); obj.a = 'www'; console.log(obj.a); // 1 for(let key in obj){ console.log(key); // b }; console.log(Object.values(obj)); // [2]
2. 严格模式:
注意:"use strict"; 必须放在js文件的第一行或者是函数的第一行;
2.1 变量必须先声明,再使用
2.2 This不允许指向全局对象,返回的是undefined
2.3 关于arguments
2.4 对于只读属性,不能够重新赋值
<script>
'use strict' // this不允许指向全局对象 function fn1(){ console.log(this); }; fn1(); // undifined // 不允许arguments重新赋值 function fn2(){ console.log(arguments); // Arguments(4) [1, 2, 3, 4, callee: (...), Symbol(Symbol.iterator): ƒ] console.log(Array.prototype.slice.call(arguments)); // (4) [1, 2, 3, 4] // arguments = 'hello'; // console.log(arguments); //会报错 } fn2(1,2,3,4); // 不再追踪参数的变化 function fn3(num){ num++; console.log(arguments); // Arguments(3) [2, 3, 4, callee: (...), Symbol(Symbol.iterator): ƒ] }; fn3(2,3,4); // 不允许使用callee function fn4(){ console.log(arguments.callee);// 获取的是函数本身 }; // fn4(); // 不允许修改对象的只读属性,否则会报错 let obj = { a : 10 }; Object.defineProperty(obj,'a',{ // writable: false, configurable: false, enumerable: false }); obj.a = 'hello'; console.log(obj); // {a: "hello"} </script>
3. 数组扩展:
Array.of() 将一组值转为一个数组,弥补Array构造函数的不足
find() 返回第一个符合条件的元素;
findIndex() 返回第一个符合条件的元素的下标
Includes() 不仅可以在数组中使用,也可以在字符串中使用;判断一个元素是否存在,返回的是一个布尔值;
<script> let arr = new Array(5); console.log(arr); //(5) [empty × 5] let arr1 = [5]; console.log(arr1); //[5] let arr2 = Array.of(12, 24, 34); console.log(arr2); // (3) [12, 24, 34] let arr3 = [1, 2, 3, 4, 5, 6, 7]; let x = arr3.find((item, index, array) => { // console.log(item,index,array); return item > 3; }); console.log(x); // 4 let x2 = arr3.findIndex(item => item > 3); console.log(x2); // 3 console.log(arr3.includes('hello')); //false console.log(arr3.includes(4)); // true let str = 'hello'; console.log(str.includes('hello')); // true console.log(str.includes('he')); // true </script>
深拷贝:
递归实现深拷贝:
let obj = { a: 1, b: 'hello', c: undefined, arr: [12, 34], ob: { ha: 'haha' }, fn: function () { console.log('fn'); } }; let copy = JSON.parse(JSON.stringify(obj)); // 不能拷贝undefined和函数 console.log(copy); // 递归实现深拷贝 function deepCopy(obj, newObj = {}) { for (let key in obj) { if (typeof obj[key] === 'object') { newObj[key] = Array.isArray(obj[key]) ? [] : {}; deepCopy(obj[key], newObj[key]); } else { newObj[key] = obj[key]; }; }; return newObj; }; let dc = deepCopy(obj); dc.arr[0] = 3; console.log(dc, obj);