当前位置: 首页 > news >正文

一个样例让你明确原型对象和原型链

开篇

之前对js中的原型链和原型对象有所了解,每当别人问我什么是原型链和原型对象时,我总是用非常官方(事实上自己不懂)的解释去描写叙述。有一句话说的好:假设你不能把一个非常复杂的东西用最简单的话语描写叙述出来,那就说明你没有真正的理解。

近期正在读《Javascript高级程序设计》,书中对原型对象和原型链的描写叙述让我受益匪浅,以下仅用一个对照性的样例来说明。

我们常常会这么写

    function Person () {
        this.name = 'John';
    }
    var person = new Person();
    Person.prototype.say = function() {
        console.log('Hello,' + this.name);
    };
    person.say();//Hello,John

上述代码非常easy,Person原型对象定义了公共的say方法,尽管此举在构造实例之后出现,但由于原型方法在调用之前已经声明,因此之后的每一个实例将都拥有该方法。从这个简单的样例里,我们能够得出:

原型对象的用途是为每一个实例对象存储共享的方法和属性。它不过一个普通对象而已。而且全部的实例是共享同一个原型对象,因此有别于实例方法或属性。原型对象仅有一份。

所以就会有例如以下等式成立:

    person.say == new Person().say

可能我们也会这么写

    function Person () {
        this.name = 'John';
    }
    var person = new Person();
    Person.prototype = {
        say: function() {
            console.log('Hello,' + this.name);
        }
    };
    person.say();//person.say is not a function

非常不幸,person.say方法没有找到,所以报错了。事实上这样写的初衷是好的:由于假设想在原型对象上加入很多其它的属性和方法,我们不得不每次都要写一行Person.prototype,还不如提炼成一个Object来的直接。可是此样例巧就巧在构造实例对象操作是在加入原型方法之前,这样就会造成一个问题:
var person = new Person()时,Person.prototype为:Person {} (当然了,内部还有constructor属性),即Person.prototype指向一个空的对象{}。

而对于实例person而言,其内部有一个原型链指针proto,该指针指向了Person.prototype指向的对象,即{}。接下来重置了Person的原型对象,使其指向了另外一个对象,即

 Object {say: function}

这时person.proto的指向还是没有变。它指向的{}对象里面是没有say方法的,由于此报错。

从这个现象我们能够得出:

在js中,对象在调用一个方法时会首先在自身里寻找是否有该方法。若没有。则去原型链上去寻找,依次层层递进,这里的原型链就是实例对象的proto属性

若想让上述样例成功执行,最简单有效的方法就是交换构造对象和重置原型对象的顺序,即:

    function Person () {
        this.name = 'John';
    }
    Person.prototype = {
        say: function() {
            console.log('Hello,' + this.name);
        }
    };
    var person = new Person();
    person.say();//person.say is not a function

一张图让你秒懂原型链

事实上。只须要明确原型对象的结构就可以:

    Function.prototype = {
        constructor : Function,
        __proto__ : parent prototype,
        some prototype properties: ...
    };

总结:

函数的原型对象constructor默认指向函数本身。原型对象除了有原型属性外,为了实现继承,另一个原型链指针proto,该指针指向上一层的原型对象,而上一层的原型对象的结构依旧相似,这样利用proto一直指向Object的原型对象上,而Object的原型对象用Object.proto = null表示原型链的最顶端,如此变形成了javascript的原型链继承,同一时候也解释了为什么全部的javascript对象都具有Object的基本方法。

Blog同步

相关文章:

  • 网络营销经历过哪三次革命?
  • 自己定制Linux发行版(资料)
  • UVA 10539 Almost Prime Numbers
  • HashMap和HashTable的区别
  • [js高手之路] dom常用API【appendChild,insertBefore,removeChild,replaceChild,cloneNode】详解与应用...
  • Linux文件系统之新建分区(fdisk命令)
  • IIS并发连接数和数据库连接池
  • 架构探险——从零开始写Java Web框架》第二章照作
  • Linux下基于nw音乐电台
  • Easyui datagrid 分页参数自定义名称+额外参数
  • 在Linux环境下mysql的root密码忘记解决方法
  • 软件工程作业 - word count
  • 怎样通过Java程序提交yarn的mapreduce计算任务
  • netstat 查询网络结构的用法
  • HDU 5298 Solid Geometry Homework 暴力
  • 【翻译】babel对TC39装饰器草案的实现
  • Android Studio:GIT提交项目到远程仓库
  • js ES6 求数组的交集,并集,还有差集
  • Js基础知识(四) - js运行原理与机制
  • leetcode388. Longest Absolute File Path
  • Linux下的乱码问题
  • PHP 7 修改了什么呢 -- 2
  • Sass 快速入门教程
  • uni-app项目数字滚动
  • 搞机器学习要哪些技能
  • 技术胖1-4季视频复习— (看视频笔记)
  • 聚簇索引和非聚簇索引
  • 如何打造100亿SDK累计覆盖量的大数据系统
  • 入门到放弃node系列之Hello Word篇
  • 通过来模仿稀土掘金个人页面的布局来学习使用CoordinatorLayout
  • 微服务入门【系列视频课程】
  • 我的业余项目总结
  • Spark2.4.0源码分析之WorldCount 默认shuffling并行度为200(九) ...
  • ​【原创】基于SSM的酒店预约管理系统(酒店管理系统毕业设计)
  • $.ajax中的eval及dataType
  • (10)STL算法之搜索(二) 二分查找
  • (11)MSP430F5529 定时器B
  • (6)设计一个TimeMap
  • (待修改)PyG安装步骤
  • (附源码)springboot高校宿舍交电费系统 毕业设计031552
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (强烈推荐)移动端音视频从零到上手(上)
  • (一)ClickHouse 中的 `MaterializedMySQL` 数据库引擎的使用方法、设置、特性和限制。
  • (转)eclipse内存溢出设置 -Xms212m -Xmx804m -XX:PermSize=250M -XX:MaxPermSize=356m
  • (转)详解PHP处理密码的几种方式
  • ./和../以及/和~之间的区别
  • .net core 3.0 linux,.NET Core 3.0 的新增功能
  • .Net IOC框架入门之一 Unity
  • .NET Standard / dotnet-core / net472 —— .NET 究竟应该如何大小写?
  • .net 发送邮件
  • .NET中的Exception处理(C#)
  • /proc/interrupts 和 /proc/stat 查看中断的情况
  • :“Failed to access IIS metabase”解决方法
  • @Documented注解的作用
  • @RequestBody详解:用于获取请求体中的Json格式参数