继承
构造函数继承
优点
- 相比原型链。可以在
子类
的构造函数中 向父类
传递参数
缺点
- 必须 在构造函数中定义方法,且函数不能重用
子类
无法访问父类
原型链上的方法
function Father(name){
this.colors= ["red", "blue","green"]
}
function Son(){
//继承 Father
Father.call(this,'Father');
}
let instance= new Son()
Son.colors.push("black ")
console.log(Son.colors); //"red, blue, green, black.
let instance= new Son()
console.log (instance. colors);//"red, blue, green
组合继承
优势
- 结合了原型链和 构造函数继承
- 保留了
instanceof
和isPrototypeOf()
方法
function Father(name){
this.colors= ["red", "blue","green"]
this.name= name
}
Father.prototype.sayName = function(){
console.log(this.name);
}
function Son(name, age){
// 继承属性
Father.call(this, name)
this.age=age
}
// 继承方法
Son.prototype = new Father()
Son.prototype.sayAge = function(){
console.log(this.age)
}
let instance= new Son("Nicholas", 29)
instance.colors.push("black")
console.log(instance.colors);//"red, blue, green, black
instance.sayName() //Nicholas
instance.savAge() //29
let instance2= new Son("Greg", 27)
console.log (instance.colors);//"red, blue, green
instance2.sayName()//"Greg"
instance2.savAge()//27
深拷贝继承
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
console.log('hello person')
}
function Student(name){
Person.call(this,name)
}
function deepCopy(obj){
let newObj = Array.isArray(obj)?[]:{}
for(let i in obj){
if(obj.hasOwnProperty(i)){
if (typeof i === 'Object'){
newObj[i] = deepObj(obj[i])
}else{
newObj[i] = obj[i]
}
}
}
return newObj
}
Student.prototype = deepCopy(Person.prototype)
Student.prototype.constructor = Student // 把预定义属性改回来
Student.prototype.say = function(){
console.log('hello Student')
}
let stu = new Student()
let per = new Person()
stu.say() // hello Student
per.say() // hello person
寄生组合继承
- 解决了 组合继承效率问题( 调用两次父类)
function Father(name){
this.colors= ["red", "blue","green"]
this.name= name
}
Father.prototype.sayName = function(){
console.log(this.name);
}
function Son(name, age){
Father.call(this, name)
this.age=age
}
Son.prototype = new Father()
Father.prototype.constructor= Son //第一次调用 SuperType()
Son.prototype.sayAge = function(){
console.log(this.age)
}
以下不借助构造函数
简单原型继承
影响: 影响父类
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
console.log('hello person')
}
function Student(name){
this.eyes = "两小只";
}
Student.prototype = Person.prototype //直接赋值
Student.prototype.say = function(){
console.log('hello Student')
}
let stu = new Student()
let per = new Person()
stu.say() // hello Student
per.say() // hello Student
组合继承
解决简单原型继承的问题
function Person(name){
this.name = name;
}
Person.prototype.say = function(){
console.log('hello person')
}
function Student(name){
this.eyes = "两小只";
}
function mid(){
}
mid.prototype = Person.prototype // 利用空函数来
Student.prototype = new mid()
Student.prototype.constructor = Student // 把预定义属性改回来
Student.prototype.say = function(){
console.log('hello Student')
}
let stu = new Student()
let per = new Person()
stu.say() // hello Student
per.say() // hello person
迭代器与可迭代协议
在日常使用中
let arr = [1,2,3]
for (let arrKey in arr) {
console.log(arrKey)
}
for (let number of arr) {
console.log(number)
}
// 上述可以执行 下述不可以 报错
// TypeError: obj is not iterable
let obj = {
1:'a',
2:'b',
3:'c',
}
for (let objKey in obj) {
console.log(objKey)
}
for (let objElement of obj) {
console.log(objElement)
}
为什么 数组可以使用for
而 obj
不可以
首先,先要 明白两个协议
了解到。数组 和 obj 差别在于[Symbol.iterator]
接下来我们就在对象里面实现这个协议.
根据 迭代器协议
可知。 我们需要 返回一个对象。 对象里面包含next
方法。还要包含done
和 value
属性(具体请见迭代器协议)
let obj = {
1:'a',
2:'b',
3:'c',
}
obj[Symbol.iterator] = function(){
let objValues = Object.values(obj)
let index = 0
return {
next(){
if(index >= objValues.length){
return {
done: true
}
} else {
return {
done: false,
value: objValues[index++]
}
}
}
}
}
for (let objKey in obj) {
console.log(objKey) // 1 2 3
}
for (let objElement of obj) {
console.log(objElement) // a b c
}
这时候我们就可以让obj
进行循环了
Generator
有关Generator 就不在多做叙述了。没有了解的请查看阮一峰老师的ES6入门
这里提供一个简单的例子
function* fn(){
yield 1;
yield 2;
yield 3;
}
let f = fn();
//console.log(f); // 返回一个函数 不会立即执行
//console.log(f.next()); // 输出类似 迭代器的返回对象
for(let val of f){
console.log(val); // 1 2 3
}
做异步
function*fn(){
yield new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("a");
resolve(1);
},500);
});
yield new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("b");
resolve(2);
},500);
});
yield new Promise((resolve,reject)=>{
setTimeout(()=>{
console.log("c");
resolve(3);
},500);
});
}
// 会一起执行
//let f = fn()
//for (let fElement of f) {
// console.log(fElement)
//}
function co(fn){
let f = fn(); // 返回了一个可迭代
function next(data){
let result = f.next();
console.log(result) // {done: value: promise}
if(!result.done){
// 上一个异步走完了,再执行下一个异步
result.value.then((info)=>{
console.log(info,data);
next(info);
});
}
}
next();
}
co(fn);
由上面注释可知。如果我们用 for
直接迭代。则会直接执行。但是我们希望它会分步执行。所以这时候就需要了一个函数 (同时也是以可库co
)
co
函数的作用,根据 Generator
每个返回值 { done:false/true value: Promise}. 根据 done
来 promise
执行完在执行下个 类似于 Async/ await