类的继承和判断父子关系
console.log("——————————————————————第一种继承:原型链继承——————————————————————")
//父类型
function Person(name){
this.name=name
this.action=["吃","喝","拉","撒"]
}
Person.prototype.name="婴儿"
Person.prototype.move=function(){
console.log(this.name+"在走路")
}
//对象原型(__proto__)和构造函数原型对象(prototype)里面都有一个属性constructor,constructor我们称为构造函数,因为它指向的是构造函数本身
console.log(new Person().constructor===Person)//true
console.log(new Person().constructor===Person.prototype.constructor)//true
//子类型
function Worker(name){
this.money=1000
}
//原型链继承
Worker.prototype=new Person()
console.log(Worker.prototype.constructor)//这里会指向Person构造函数,所以我们得修正一下
Worker.prototype.constructor=Worker
//实例化
var person=new Person("爸爸")
var w1=new Worker("儿子")
person.move()//爸爸在走路
w1.move()//undefined在走路,,如果添加this.name=name那有啥继承意义
//实例既是父类的实例,也是子类的实例
console.log(w1 instanceof Person)//true
console.log(w1 instanceof Worker)//true
//【缺点】******:
//①可以方便继承父类型的原型中的方法,但是单纯属性的继承无意义,我想要在这个方法的基础上传参那怎么办?
//②给子类原型添加或者重写方法的代码一定要放在替换原型的语句Worker.prototype=new Person()之后。
//③通过原型链实现继承时,不能使用对象字面量创建原型方法,因为这样做就会重写原型链
//④难以实现多继承,会共享属性比如:
w2=new Worker()
console.log(w1.action)//w1只会人类都懂的吃喝拉撒行为
//w2很特别,学到了新技能————飞
w2.action.push("飞")
console.log(w2.action)//["吃", "喝", "拉", "撒", "飞"]
console.log(w1.action)//["吃", "喝", "拉", "撒", "飞"]
//等等为什么w1也会飞了?!
//
//——————————————————————第二种继承:借用构造函数——————————————————————
console.log("——————————————————————第二种继承:借用构造函数——————————————————————")
//使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)
function Actor(name){
Person.call(this,name)
this.money=10000
}
let a1=new Actor("成龙")
console.log(a1.name)//成龙 //传参成功
//【缺点】******:
//①实例并不是父类的实例,只是子类的实例
console.log(a1 instanceof Person)//false
console.log(a1 instanceof Actor)//true
//②无法使用原型protoyype定义的属性,只能使用构造函数内定义的
//a1.move() //Error
//③无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
//引用
console.log("——————————————————————第三种继承:组合继承——————————————————————")
//通过调用父类构造,继承父类的属性并保留传参的优点,然后通过将父类实例作为子类原型,实现函数复用
function Student(name,score){
Person.call(this,name)//第一步
this.score=score
}
//第二步
Student.prototype=new Person()
Student.prototype.constructor=Student
Student.prototype.showScore=function(){console.log(this.name+"考试得分:"+this.score)}
var s1=new Student("罗杰",100)
s1.move()//罗杰在走路
s1.showScore()//罗杰考试得分:100
var s2=new Student("杰罗",99)
s2.action.push("打游戏")
console.log(s2.action)//["吃", "喝", "拉", "撒", "打游戏"]
console.log(s1.action)//["吃", "喝", "拉", "撒"]
判断JS的类型
JS基本有
·5种简单数据类型:String,Number,Boolean,Null,undefined。
·1种复杂的数据类型Object。
ES6 引入了一种新的原始数据类型Symbol,表示独一无二的值。它是 JavaScript 语言的第七种数据类型。它最大的用处是定义对象唯一的属性名字。
let s1 = Symbol('luo');
let s2 = Symbol('jie');
console.log(s1);//Symbol(luo)
1. typeof
可以判断出String,Number,Boolean,Undefined,Symbol,判断 typeof(null)
时值为 Object,判断数组和对象时值均为 Object
2. instanceof
instanceof 可以判断一个引用是否属于某构造函数,还可以在继承关系中用来判断一个实例是否属于它的父类型。本质上是检测对象的原型链(proto)上是否有指定函数的.prototype原型对象
3. Object.prototype.toString.call()
对于所有基本的数据类型都能进行判断,即使是 null 和 undefined
console.log(Object.prototype.toString.call(null))
console.log(Object.prototype.toString.call([1,2,3]))
console.log(Object.prototype.toString.call(undefined))
Object是js中所有其他数据类型的父类,所有的数据类型都继承了Object。但是无论是string还是array都是会重写这个tostring方法的。
4. Array.isArray()
用于判断是否为数组
手动实现上文中的instanceof
function my_instanceof(obj,class_fun){
const SP=class_fun.prototype//构造函数原型
while(obj!==null){
//===严格比较,同类型同值
if(obj===SP)return true
obj=obj.__proto__// 沿着原型链重新赋值
}
if(obj===null)return false
}