javascript基础系列之类相关知识

175 阅读2分钟

instanceof

JS中可以通过instanceof操作符来判断某个对象是否为某个类的实例。其原理为从实例开始,遍历其自身/原型/原型的原型....由下至上追溯__proto__属性,

其实现如下:

function instanceof (instance, class){
    var proto = class.prototype
    var insProto = instance.__proto__
    while(true){
        if(insProto === null){
            return false
        }
        if( insProto === proto){
            return true
        }
        insProto = insProto.__proto__
    }
}

注意

  1. 完全重写原型对象,如下:这样写虽然使用instanceof依然可以判断sub是subType()的实例,但是subType的constructor属性已经不存在了,因此要手动去修复这个属性,值得注意的是,在要使用Objesct.defineProperty,因为默认constructor属性是不可枚举的(enumberable:false)
function subType = (){
    
}
subType.prototype ={ }

var sub = new subType()
  1. 红宝书P157,注意添加原型链的时机:给原型添加方法的代码 一定要在替换原型对象之后 否在会被新的对象覆盖掉
function Person(){

}

var friend = new Person()

Person.prototype={
    constructor:Person,
    name:"xjm",
    age:25,
    sayName(){
        console.log(this.name)
    }
}

friend.sayName()    //报错,找不到sayName属性/方法

new.target:指向被new调用的【构造函数】

在创建实例dog的时候,调用了Dog的构造函数,Dog类和Animal的构造函数都运行,而且输出的new.target都是Dog。

        class Animal {
            constructor(name, age) {
                console.log(new.target)         //Dog
                if (new.target === Animal) {
                    throw new Error('Animal class can`t instantiate');
                }
                //模仿抽象方法
                if (new.target !== Animal && !new.target.prototype.hasOwnProperty('getName')) {
                    throw new Error('please overwrite getName method');
                }
                this.name = name
                this.age = age
            }
            // 其他代码
            //...
        }

        class Dog extends Animal {
            constructor() {
                console.log(new.target)         //Dog

                super('dog', 1)
            }
        }
        
        const dog = new Dog()

在js中是没有抽象类的概念的,因此可以使用new.target来模仿抽象类/抽象方法。 在js中一切都可以是对象,但是对象的类型只有在运行的时候才确定个,因此虽然这个方法可以模拟抽象类/抽象方法,但是只有到了函数运行的时候才会报错。

class person{
    constructor(){
        if(new.target === 'person'){
            throw new Error('不能实例化抽象类')
        }
        if (new.target !== person && !new.target.prototype.hasOwnProperty('getName')) {
            throw new Error('没有重写抽象方法getName');
        }
    }
}