前言
原型是JavaScript中一个比较难理解的概念,原型相关的属性也比较多,对象有“ [[prototype]]”属性,函数对象有“ prototype”属性,原型对象有“ Constructor”属性。
认识原型(什么是原型)
开始原型的介绍之前,我们首先说说什么是原型?
定义
在[JavaScript]中,原型也是一个对象,通过原型可以实现对象的属性继承,JavaScript的对象中都包含了一个”” [原型]]“内部属性,这个属性所对应的就是该对象的原型。” [ [原型]]“作为对象的内部属性,不能被直接访问的。”为了方便查看一个对象的原型,Chrome等大型浏览器厂商提供了” __ proto __ “这个非标准的访问器(ECMA了标准)对象原型访问器“ Object.getPrototype(Object)”)
实例分析
js 函数Animal (名称,类型){ this 。名称=名称; 这个。类型=类型; 这个。getInfo = function (){ 控制台。信息(“当前动物属性==>” ,这个。名字+ ‘是’ + 这个。类型)} } 让狗= 新的动物
("狗", "犬科哺乳动物") // 当前动物属性==> 狗is犬科哺乳动物
Step-->1: 查看对象 dog 的原型
```js
console.info("__proto__",dog.__proto__);
// __proto__ Objectconstructor: ƒ Animal(name, type)__proto__:
console.info("constructor=====>",dog.constructor)
//constructor=====> ƒ Animal(name, type) {
// this.name = name;
// this.type = type;
// this.getInfo = function(){
// console.info("当前动物属性==>",this.name + 'is' + this.type)
结果分析
- “ Animal {}”对象就是dog的原型,通过Chrome展开可以看到,“ Animal {}”作为一个原型对象,也有“ __ proto __ ”属性(对应原型的原型)* 在这段代码中,还用到“构造函数”属性。在JavaScript的对象原型对象中。还包含一个“构造函数”属性,这个属性对应创建所有指向该原型的实例的构造函数
js //扩展可以判断一个对象是不是类型类型function isArray ( arr ){ return arr 。构造函数。toString ()。indexOf (“ Array” )> - 1 ; }
*在这里,狗对象本身没有“构造”这个属性,但是通过原型链查找,这到了狗的原型(狗。原)的“构造”属性,并找到了动物函数
步骤- > 2:(狗查看对象狗的原型__原__)的原型
既然狗的原型“动物{}”也是一个对象,那么我们就同样可以来查看狗的原型(狗。原)的原型
js
控制台。信息(狗。 proto =动物。原型)
控制台。信息(动物,原型。 proto )
控制台。信息(动物,原型。构造函数)
控制台。信息(动物,原型。构造=动物) ```
结果分析
- 首先看"dog.proto === Animal.prototype",在 JavaScript 中,每个函数都有一个 prototype 属性,当一个函数被用作构造函数来创建实例时,该函数的 prototype 属性值将被作为原型赋值给所有对象实例(也就是设置实例的__proto__属性),也就是说,所有实例的原型引用的是函数的 prototype 属性。了解了构造函数的 prototype 属性之后。一定就会明白为什么第一句是 true 了
- 当通过"Animal.prototype.proto"语句获取dog 对象原型的原型时候,将得到"Object{}"对象,后面将会看到所有对象的原型都将追溯到"Object{}"对象。
- 对于原型对象"Animal.prototype"对象的"constructor"根据前面的介绍,将对应 Animal 函数本身。
通过上面可以看到,"Animal.prototype"对象和 Animal 函数对象通过"constructor"和 "prototype"属性实现了相互引用
Step–>3: 查看对象 Object 的原型
通过前一部分可以看到,将的原型的原型是“ Object {}”对象。实际上在JavaScript中,所有对象的原型都将将转向“ Object {}”对象。下面通过一段代码看看” Object { }“对象:
JS 控制台日志(动物原型。原 ===对象原型。); 控制台日志(typeof运算对象); 控制台日志(对象); 控制台日志(对象原型。); 控制台。日志(对象原型。原); 。控制台日志(对象原型构造); `
结果分析
- 对象对象本身是一个函数对象。*既然是对象函数,就肯定会有原型属性,所以可以看到“的Object.prototype”的值就是“对象{}”这个原型对象。反过来,当访问” Object.prototype中中‘对象的’构造‘这个属性的时候,就得到了Obejct函数。另外,当通过’的Object.prototype中。原 ‘获取对象原型的原型的时候,将会得到’空“,初步“ Object {}”原型对象就是原型链的终点了。
步骤-> 4:查看对象功能的原型
在上面的示例中,Animal是一个构造函数,在JavaScript中函数也是对象,所以,我们也可以通过“ __ proto __ ”属性来查找动物函数对象的原型。
js
控制台。日志(动物。 proto =函数。原型);
控制台。日志(动物。构造函数=功能)
控制台。log (typeof函数);
控制台。log (函数);
控制台。日志(函数。原型);
安慰。日志(函数。原型。 proto );
控制台。log (函数,原型,构造器); ```
结果分析
- 在JavaScript中有个Function对象(类似Object),这个对象本身是个函数;所有的函数(包括Function,Object)的原型(__ proto __)都是“ Function.prototype”。* Function对象作为一个函数,就会有原型属性,该属性将对应“功能(){}”对象。* 功能对象作为一个对象,就有” 原 “属性,该属性对应” Function.prototype的“也就是说,”功能。原 === Function.prototype的“ * 对于功能的原型对象”Function.prototype的“,该原型对象的” 原 “属性将对应”对象{}”
#####比较原型和__原型__
对于“原型”和“ 原 ”这两个属性有的时候可能会弄混,“ Person.prototype的”和“的人。原 ”是完全不同的。
在这里对“ prototype”和“ __ proto __ ”进行简单的介绍:
- 对于所有的对象,都有__ proto 属性,这个属性对应该对象的原型* 对于函数对象,除了 proto 属性之外,还有prototype属性,当一个函数被构造构造来创建实例时,该函数的原型属性值将被作为原型赋值给所有对象实例(也就是设置实例的 proto __属性)
对于上图的总结如下:
- 所有的对象都有“ __ proto __ ”属性,该属性对应该对象的原型所有的函数对象都有“ prototype”属性,该属性的值会被赋值给该函数创建的对象的“ __ proto __ “属性所有的原型对象都有“构造函数”属性,该属性对应创建所有指向该原型的实例的构造函数函数对象和原型对象通过“原型”和“构造函数”属性进行相互关联因为每一个对象和原型都有原型,对象的原型指向对象的父,而父的原型又指向父的父,这种原型层层连接起来的就构成了原型链。
hasOwnProperty
“ hasOwnProperty”是“ Object.prototype”的一个方法,该方法能判断一个对象是否包含自定义属性而不是原型链上的属性,因为“ hasOwnProperty”是JavaScript中唯一一个处理属性但不查找原型链的函数。
相信你还记得文章最开始的例子中,通过dog我们可以访问“ constructor”这个属性,并得到dog的构造函数动物。这里结合“ hasOwnProperty”这个函数就可以看到,dog对象并没有“ constructor”这个属性。
从下面的输出可以看到,“构造”是狗的原型(狗。原)的属性,但是通过原型链的查找,狗对象可以发现并使用“构造”属性。
** “ hasOwnProperty”还有一个重要的使用场景,就是利用遍历对象的属性。**
的JS启动人(姓名,年龄){this.name =名称; 这个年龄=年龄; } Person.prototype.getInfo =函数(){的console.log(this.name +“是” +此。年龄+“岁”);}; var will = new Person(“ Will”,28);对于(遗嘱中的attr属性){console.log(attr);} //名称//年龄// getInfo for(var attr in will){if(will .hasOwnProperty(attr)){console.log(attr);}} // //名称年龄
摘要翻译者介绍了JavaScript的中原型相关的概念,对于原型可以归纳出以下某些点:所有的对象都有“ [[原型]]”属性(通过__原
__访问),属性该对应对象的原型所有的函数对象都有“原型”属性,该属性的值会被赋值给该函数创建的对象的“ __ proto __ ”属性所有的原型对象都有“ constructor”属性,该属性对应创建所有指向该原型的实例的构造函数函数对象和原型对象通过“ prototype”和“ constructor”属性进行相互关联通过这些图片,相信一定可以对原型有个清晰的认识。