继承
原型链继承:
将子类的原型(prototype)连接到父类的实例,将子类的原始对象替换为父类的实例,从而拿到父类的所有方法和属性
不支持多重继承,因为prototype很明显会被新的父类替换
其次,创建子类实例的时候,无法向父类构造函数传递参数
同时,来自原型对象的引用属性是所有子类共享的,因为原型链向上寻找的时候共享了父类的实例
这显然不符合继承的原则
构造继承:
用call或者apply将父类中通过this绑定的属性和方法拷贝(借用)过来,又被称为用父类的构造函数增强子类
这里可以看到父类被子类调用,从而将子类中this指向父类。
function A(name){
this.name = name;
}
function a(){
A.call(this,"nickname");
this.age = 12;
}
let aa = new a();
console.log(aa.name,aa.age);
很明显。这只能继承父类的实例方法和属性,不能继承其原型方法和属性。
组合继承:
ES6中extends的实现方式
前两者融合,用原型继承得到父类的原型方法和属性,用构造继承得到父类的实例方法和属性。
function A(name){
this.name = name;
}
A.prototype.printName = ()=>{
console.log(this.name);
}
function a(name,age){
a.call(this,name);
this.age = age;
}
a.prototype = new A();
a.prototype.constructor = a;
let aa = new a("nickname",18);
console.log(aa.age,aa.name);
aa.printName();
注意,这里要修复原型对象的构造器的指向问题,很明显,由于a的原型对象是父类A的实例对象,这个实例对象的原始构造函数很明显是A,但是a的原型对象的构造函数本应当是a本身,这里就应该做一次重新的指定。
几乎没有什么大问题,除了调用了两次父类的构造函数(后来的子类实例属性和方法覆盖了父类的实例属性和方法),消耗了点内存
寄生组合继承:
function A(name){
this.name = name;
}
function a(name,age){
A.call(this,name);
this.age = 12;
}
(
function super(){};
super.prototype = A.prototype;
a.prototype = new super();
)()
let aa = new a("nickname",18);
用一个空的没有实例方法和属性的super砍掉父类的实例方法和属性,解决了组合继承那多出来的一点内存,但是实现比较复杂
this
函数被谁调用,this就指向谁。
所以this是根据函数运行时的环境决定的,而不是这个函数被创建时决定的。
匿名函数的this是指向window的,你可以认为这里是来自window的调用(包括延时函数,是绑定在window上的方法,也是window做的调用)
在使用call和apply,bind的时候,this会被指定,以改变某个函数运行时候的上下文(改变被调用函数的this,让其this指向第一个参数),实际上也就是让第一个参数去调用函数,跟第一条规则丝毫不冲突。
的函数不改变当前this,所以你可以使用
function a(){
this.name = "nickname";
document.getElementById("123").addEventListener('click',(e)=>{
console.log(this.name);
})
}
这里要是使用匿名函数做回调函数,函数里的this应当指向触发事件的元素本身,也就是e.target,但是箭头函数不改变this,所以这里的this就指向a了。多用于react中传递给子组件的方法。
如果你想要用匿名函数达成同样的效果,你可以这样写
function a(){
this.name = "nickname";
let _this = this;
document.getElementById("123").addEventListener('click',function(e){
console.log(_this.name);
})
}
数据类型
number,object,boolean,undefined,string,null,symbol(标志一个变量独一无二)
注意基本类型是:Number,String,Boolean,Undefined,Null,Symbol
以及函数类型:function
判断数据类型可以用typeof,但是[],{},null都会输出object
可以使用Object.prototype.toString.call(判断对象)来进行判断。
当然也可以使用constructor进行判断
比如 [].constructor === Array
还有instanceof
下一篇讨论js里常遇到的算法。