javascript原型的继承


1.原型继承的方法

1.运用原型的原型__proto__


function Text(name) {
      this.name = name;
    }
    Text.prototype.show = function () {
      console.log(this.name);
    };
    function Text2(name) {
      this.name = name;
    }
    let a = new Text2("橘子");
    Text2.prototype.__proto__ = Text.prototype;
    a.show();    

同样的也可以使用专业方法来实现赋值Object.setPrototypeOf(Text2.prototype.__proto__,Text.prototype);
将构造函数Text的原型赋值给Text2原型的原型,这Text2的原型链上就有Text的原型我们就可以使用a访问到show函数,原型链如下图
在这里插入图片描述

图中Text2原型的原型被Text的原型所代替即a的原型链为-Text2的原型-Text的原型-Text原型的原型-NULL,所以a实例可以访问到show方法打印出橘子

  1. 运用Object.creat()方法
 function Text(name) {
      this.name = name;
    }
    Text.prototype.show = function () {
      console.log("show");
    };
    function Text2() {
      this.name = name;
    }
    Text2.prototype = Object.create(Text.prototype);
    Text2.prototype.show2 = function () {
      console.log("show2");
    };
    let a = new Text2();
    a.show2();

在这里插入图片描述
使用Object.creat()方法新建了一个对象,将新对象的原型设置为Text的原型,这里需要注意的是,创建了新对象再添加了show2方法而且实例化a对象是在创建对象之后,使用a.showa.show2都可以正常运行

2.原型继承带来的问题和解决方法

  1. 在使用第二种方法时,会丢失掉constructor属性,如果使用console.log(Text2.prototype.constructor);
    来访问不会报错但会找到Text,和想找到Text2就差之甚远了
    怎么解决呢?
    只需要给他添加上constructor属性并赋值为Text2就好啦,如下
    Text2.prototype.constructor = Text2;
  2. 接1的背景,使用for in循环遍历对象时会查找原型链中的属性,所以当我们遍历a实例时会遍历出来如下图的结果在这里插入图片描述
    实际操作中并不希望将constructor属性遍历出来解决办法如下:
  // Text2.prototype.constructor = Text2;        //注意这里将第一个问题的解决方法注掉了
    Object.defineProperty(Text2.prototype, "constructor", {
      value: Text2,
      enumerable: false,
    });

这个解决办法显然是第一个办法的改进版本。


在文末再谈一下__proto__

 let text = {};
    text.__proto__ = {
      show() {
        console.log("橘子");
      },
    };
    text.show();
    text.__proto__ = "大兔子";
    text.show();

以上代码会输出两个橘子,明明在我倒数第二行的时候,我改变了他的原型啊,为什么结果还会是两个橘子呢?

let text = {
      action: {},
      get __proto__() {
        return this.action;
      },
      set __proto__(obj) {
        if (obj instanceof Object) {
          this.action = obj;
        }
      },
    };

就是上面的原因啦,因为他是个 getter 和setter 会对输入的值进行判断,但是我就是想改变text.__proto__的值那我该如何操作呢?让对象不继承Object.prototype就行了没错,就是下面的方法,

 let text = Object.create(null);
    text.__proto__ = 99;
    console.dir(text.__proto__);

好了今天的原型继承知识就告一段落了 Bye~~

猜你喜欢

转载自blog.csdn.net/qq_45753500/article/details/105456507