对于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中的原型属性,每个对象都会拥有。