对于JavaScript的__proto__以及prototype与constructor的理解。

js是一门有趣的语音,最近一直在学习中,看了不少书籍。对于对象的一些内置特性了解的不好。

这里写一些简单的笔记,方便自己的学习

首先我自己的理解,这里面由三个对象,一个是实例,一个是构建函数,还有一个是原型。

实例可以用过__proto__查看自己的原型或者用Object.getPrototypeOf这个命令查看,一样的效果

function Demo(a){this.a = a}
undefined
var d = new Demo(99)
undefined
d.__proto__
{constructor: ƒ}
Object.getPrototypeOf(d)
{constructor: ƒ}
Demo.prototype
{constructor: ƒ}

从代码可以看出,实例可以通过__proto__查看自己的原型,这个原型可以理解为Python中的类?(也不是很对)

后续通过原型给实例添加一些属性与方法,比较像Python中的猴子补丁。

不光从实例可以看到原型,也可以通过构建函数查看原型,实例可以通过constructor查看构建函数。

d.constructor === Demo
true
d.constructor
ƒ Demo(a){this.a = a}
Demo
ƒ Demo(a){this.a = a}

既然可以看到构建函数,我们通过构建函数查看一下原型

Demo.prototype
{constructor: ƒ}constructor: ƒ Demo(a)__proto__: Object
d.__proto__
{constructor: ƒ}constructor: ƒ Demo(a)__proto__: Object
Demo.prototype === d.__proto__
true

通过演示,可以直接通过实例查看原型,也可以通过构建函数查看原型。原型有什么用,他可以在添加公用的属性与方法。

Demo
ƒ Demo(a){this.a = a}
Demo.prototype.show = function(){console.log('show'+this.a)}
ƒ (){console.log('show'+this.a)}
d.show()
VM8836:1 show99

这里面肯定有人说,可以在构建函数的地方直接定义 添加这个对象属性。

function Demo(a){
  this.a = a;
  this.show = function(){console.log('show'+this.a)}
}

但这样的话,会在每个新建的实例创建一个这个的方法,非常浪费内存空间。

所以方法在原型中添加更加合适,为什么的话,看我下面分析

function Demo(a){
  this.a = a;
  this.show = function(){console.log('show'+this.a)}
}
undefined    
Demo.prototype
{constructor: ƒ}constructor: ƒ Demo(a)__proto__: Object
Demo.prototype.show
undefined

上面的代码可以看出在构建函数内通过prototype并不能查看到原型内的一些提供给实例的公用方法或者属性,

其实也对,因为在构建函数里面定义的属性与方法每个实例都是特有的。

所以这样的话,如果想使用构建函数内定义的方法会比较麻烦,只能通过实例来调用改方法。

但如果通过原型的方式,给原型赋值属性并添加方法的方式,可以通过原型调用该方法,通过call、apply、bind的方式或者指定调用的方式来调用该方法,而且同样实例也能使用该方法。

Demo.prototype.show = function(){return this.a + 'hello' + this.b}
ƒ (){return this.a + 'hello' + this.b}
d.show()
"99helloundefined"
Demo.prototype.show.call({a:888,b:'xxx'})
"888helloxxx"
var a = 'main'
undefined
var b = 'window'
undefined
var show = Demo.prototype.show  //赋值到全局变量组
undefined
show()
"mainhellowindow"

最后来看一下原型函数,通过constructor来获取,实例与原型的constructor调用都返回原型函数

d.constructor === Demo
true
Demo.prototype.constructor ===Demo
true

最后是我前面碰到疑惑的,就是通过函数去调用__proto__获取构建函数的原型,以及constructor获取构建函数。

Demo.__proto__
ƒ () { [native code] }
Demo.constructor
ƒ Function() { [native code] }
Demo.__proto__.parent_show = function(){console.log(this.a)}
ƒ (){console.log(this.a)}

通过__proto__可以查看到构建函数的原型,也可以通过构建函数给原型给构建函数添加共有属性方法,

通过constructor可以看出构建函数的构建函数,正是Function函数。

后续还有继承,下次有空再写笔记,继续主要通过__proto__查看上级的原型,实例继承该原型的属性以及方法。

记住,任何一个函数都有prototype属性,这个属性是拿来给下级的实例调用的,所有的对象都继承或者实例来至Object函数

所以Object中的原型属性,每个对象都会拥有。