简单理解__proto__、prototype

引言

要学的东西真的越来越多,从入门开始一个个变量声明再到现在能独立完成一个项目,总觉得很多基础没有掌握好,回过头来慢慢看一些东西觉得有必要记录一下,特别是JavaScript的原型链这块。

首先,什么是__proto__、prototype,简单来说__proto__是Object的属性,prototype是Function的属性,而实际上所有所有的JavaScript内的变量也好,方法也好,一切的一切都是对象,但是为了能把这两者区分开来,特意分成了对象和函数,但实际上函数的本质也是一个对象。

先抛出一个问题,所有对象都可以使用的toString()方法我们并没有声明过,但为什么我们可以使用这个方法?这个方法存在于哪里?

属性理解

便于理解,构建一个对象和函数

  function Fun(){};
  let Obj = new Fun();
  console.log(Obj);

查看打印
在这里插入图片描述

通过new来创建一个构建函数,这里的Obj是一个对象,可以理解成通过Fun函数构建了一个实例对象Obj。
打印两者的__proto__及prototype

console.log(Obj.__proto__===Fun.prototype);

查看
在这里插入图片描述
发现两者是一样的,可以得出一个结论:由Fun构造的Obj的__proto__属性指向Fun的prototype属性,而Fun的prototype属性也就是Obj的__proto__属性到底是什么呢

console.log(Fun.prototype);

查看
在这里插入图片描述
看到constructor的时候一下子就想到了es6语法里的class ,而Fun.prototype在被调用时的constructor方法指向函数Fun(),所以可以理解成当用new构建了一个Fun的实例对象时,同时构建了一个Fun.prototype,这里把Fun.prototype称为实例原型。
所以Obj的__proto__属性实际上指向的就是构建它的函数的实例对象,我们可以对这个实例对象进行方法注册。

  function Fun(){};
  let Obj = new Fun();
  Fun.prototype.sayHello = function(){
    console.log('hello');
  };
  Obj.sayHello();

查看
在这里插入图片描述
好的,那么我们就可以知道Obj的方法是由它的构建函数的实例原型所注册的,而且发现这个实例原型也是一个对象,那么就继续找这个实例原型的构造函数的实例原型,也就是Obj.proto.proto

console.log(Obj.__proto__.__proto__);

查看
在这里插入图片描述
终于是发现了这个toString方法,到此为止,发现这个对象没有__proto__属性,那么就可以理解为这个实例原型为最初构建的实例原型,它本身就存在于JavaScript语法中。

原型链

这一层层找对象的实例原型的关系,也就被称为原型链。
对比class的继承关系,对象的原型链也是一样的,任何对象的toString方法也是由实例原型的方法继承而来的。

问题

不过随之带来的问题也是很大的,因为我们可以对这个原型实例的toString方法进行改写。

  Object.prototype.toString = function(){
    console.log('没改变而且没有返回值')
  };
  let s = Object();
  let a = s.toString();
  console.log(a);

查看
在这里插入图片描述
百度了一下别人的可以通过设置Object.create(null)防止感染
https://www.bbsmax.com/A/MyJxL26MJn/
还得好好研究一下

猜你喜欢

转载自blog.csdn.net/qq_37195804/article/details/106062568