JavaScript原型对象与原型链

2020-01-04  本文已影响0人  agamgn

一、前言

    原型和原型链是 JavaScript中不可避免需要碰到的知识点,在刚开始学习 JS 时,原型和原型链都是一个需要克服的困难。
网络上有很多讲解原型与原型链的就是放一张图,然后指来指去,很容易绕糊涂,现在我总结我对其的认识,如有错误之处,请指出。

二、前置知识

2.1构造函数

出自《你不知道的js》:在js中, 实际上并不存在所谓的'构造函数',只有对于函数的'构造调用'。

所谓的构造函数,实际上就是通过关键字new来调用的函数。

let newObj=new someFunc()  //构造调用函数

构造/new调用函数的时候做了什么new做了什么,简单说:

2.2普通对象和函数对象

    在JavaScript中一切皆对象,函数的本质也是一个对象,只不过函数的能力很强大罢了!ObjectFunction就是JavaScript中典型的函数对象。
如何区分函数对象和普通对象呢?

var obj={};
var func=function(){};
console.log( obj.constructor ); //f Object() { }
console.log( func.constructor ); //f Function() { }

结论:普通对象的构造函数是 Object() , 函数对象的构造函数是 Function();

三、原型

3.1什么是原型

在ES2019中prototype 的定义为

object that provides shared properties for other objects
给其它对象提供共享属性的对象。

也就是说,prototype 自己也是对象,只是被用以承担某个职能罢了
先看例子:

demo1.png
由上图可以得出以下结论

每声明一个函数,就会有一个产生一个原型,这个原型的 引用 就保存在 函数对象的 func.prototype 上面

3.1为什么要用原型

JS通过new来生成对象,但是仅靠构造函数,每次生成的对象都不一样。
有时候需要在两个对象之间共享属性,由于JS在设计之初没有类的概念,所以JS使用函数的prototype来处理这部分需要被共享的属性,通过函数的prototype来模拟类:
当创建一个函数时,JS会自动为函数添加prototype属性,值是一个有constructor的对象。
简单来说就是共享属性。

demo2.png
由demo可以看出原型是对象的共同属性,当其中一个对象修改其值时不会影响到原型上的值
这里同样也有一个疑问,为什么People1在给age赋值之后就不能访问原型上age的值,而People2没有age,却能访问原型上的age的值?这就需要引如原型链的概念了。

四、原型链

4.1认识proto属性

看一个例子: demo3.png

由demo可以得出结论:

4.2原型链是什么

看个例子:


demo5.png

如是以前的语法,从newObj查找func的原型,是这样的:

newObj.__proto__.__proto__ // 这种关系就是原型链

那么什么是原型链?用以下三句话理解:

4.2.1判断一个对象是否在另一个对象的原型链上

如果一个对象存在另一个对象的原型链上,我们可以说:它们是继承关系,关于JavaScript的继承,请参考JavaScript继承
方法有以下两种:
1.instanceof: 用于测试构造函数的prototype属性是否出现在对象的原型链中的任何位置

demo6.png
2.isPrototypeOf:测试一个对象是否存在于另一个对象的原型链上
demo7.png

4.2.2原型链的终点: Object.prototype

Object.prototype是原型链的终点,所有对象都是从它继承了方法和属性。

console.log(Object.getPrototypeOf(Object.prototype));// null

4.2.3原型链图

有以上可以引出这张图


demo10.png 下面是简图: demo4.png

看懂这图,基本上所有之前的疑问都可以解答了。

4.2.4原型链的作用

从什么是原型链的介绍中已经知道原型链的作用是什么了
属性查找,如果试图访问对象(实例instance)的某个属性,会首先在对象内部寻找该属性,直至找不到,然后才在该对象的原型(instance.prototype)里去找这个属性,以此类推

demo9.png
当你访问test的某个属性时,是这样进行查找的:
1.浏览器首先查找stringtest 本身
2.接着查找它的原型对象:String.prototype
3.最后查找String.prototype的原型对象:Object.prototype
4.一旦在原型链上找到该属性,就会立即返回该属性,停止查找。
5.原型链上的原型都没有找到的话,返回undefiend
4.2.4.1拒绝查找原型链

hasOwnProperty: 指示对象自身属性中是否具有指定的属性

let test ={ 'name': 'agamgn' }
test.hasOwnProperty('name');  // true
test.hasOwnProperty('toString'); // false test本身没查找到toString 

总结

代码地址

参考

上一篇 下一篇

猜你喜欢

热点阅读