Javascript之prototype、constructor、instanceof、typeof、class小议

javascript任何元素都可以看成对象,那么就存在继承及原型的概念。实例从原型继承,而这层关系就是_proto_属性的值,在JS中这个属性是不可直接访问的,是通过方法Object.setPrototypeOf及Object.getPrototypeOf来完成写和读操作的。
而对于某些对象来说除了_proto_属性,还有一个特有的属性prototype,这些对象包括函数或方法、Array、Number、String、Boolean、Date对象等,这里称它们为特殊对象,这些对象可以通过prototype来修改或增删其原型对象方法或属性。而这个prototype属性也是对象,所以其也有_proto_属性,除了这个属性外还有一个就是要说的constructor属性,而这个属性又指向上述特殊对象。上述对象创建时,其prototype属性至少都有constructor和_proto_属性,有点绕,从网上找到一份函数或方法对象的关系图:
在这里插入图片描述
对于Array、Number、String、Boolean、Date可以有类似的逻辑关系,只不过这些对象实例创建时new可有可无,例子如下:

    //通用对象
    var myobj={name:"wind"};
    console.log(myobj);//Object{name:"wind",_proto_:Object}
    //字符串对象
    var name ="stone";
    String.prototype.changename = function(){
        return "rock";
    }
    String.prototype.prigroup=function(){
       //通过this实现实例不同值
       return this.valueOf()+"CN"
    }
    String.prototype.demovalue= "sand";
    console.log(Object.getPrototypeOf(name));//String
    console.log(name.changename())//rock
    console.log(name.demovalue)//sad
    console.log(name.prigroup())//

综上所述,原型表明了继承关系,通过prototype属性既可以实现类的公用属性或方法,进一步结合this又可以实现私有化。
回到函数(方法),由上图可知,当用new操作符创建一个构造函数的实例时,此实例的_proto_属性指向构造函数的原型,那么构造函数当使用prototype来增改属性时,这些变化都被实例继承。但是如果实例里有方法或属性和原型对象的方法及函数重名,那么以实例里的方法或属性为准,这和其他面向对象语言类继承关系一样。
prototype对象也是可以修改的,如果修改后,原来旧的对象引用旧的原型,新的对象则引用新的原型。
方法或函数的prototype属性的constructor指明了构造函数,比如执行
ninja= new Ninja后,ninja.constructor=Ninja,那么也可以constructor属性来构造其他例子,比如:
var ninja2= new ninja.constructor()
总的来说:Ninja.prototype.constructor===ninja.constructor,是不是有点意思。

创建原型链式的继承最好的方法是一个对象的原型是另一个对象的实例。
比如:Subclass.prototype=new Superclass(); 这就表明Subclass的原型是Superclass,请看下例:

    function Person(){}
    Person.prototype.dance = function(){};
    function Ninja(){}
    Ninja.prototype = new Person();
    const ninja = new Ninja();
    console.log(ninja instanceof Ninja);// true
    console.log(ninja instanceof Person);//true
    console.log(ninja instanceof Object);//true

上例表明了通过修改prototype属性来实现原型链式,但是有一个问题就是prototype属性有一个constructor属性用来指明构造函数,执行function Ninja(){}后,Ninja.prototype.constructor===Ninja,但是接下来Ninja.prototype = new Person()使得prototype属性整体变了,构造函数的实例返回的是对原型的引用,所以new Person()的constructor指向Person,为了纠正过来,就得重新修改Ninja.prototype.constructor属性值,js使用的是Object.defineProperty方法:

Object.defineProperty(Ninja.prototype, "constructor", {
			  enumerable: false,
			  value: Ninja,
			  writable: true
			});

这样当执行var ninja=new Ninja()后,ninjia.constructor==Ninja.

从前面的例子得知,instanceof操作符反映的是原型链关系,原型链关系是通过prototype关系来修改,通过instanceof操作符来验证。和typeof比较起来更能说明对象间的关系,因为typeof 返回值只有六种可能: “number,” “string,” “boolean,” “object,” “function,” 和 "undefined,对于大部分对象返回的都是"object“,比如typeof 数组和typeofNull都是object,这并不能表明对象间的关系,只能显示对象的类型,而且还很粗糙。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值