熟悉软件开发的朋友都知道,原型是产品或数据系统的一个基本的实用模型,通常为示范目的或开发程序的部份结构。原型的重要性不言而喻,接下来我就会为你讲解关于JavaScript中的原型概念。
原型对象释义
每一个构造函数都有一个与之相关联的对象,该对象称之为原型对象。
每个实例对象都能共享其原型对象上的属性和方法。
原型对象的作用主要用来实现属性的继承,让实例对象能共享原型对象的属性,减少内存分配。
所以,在上一节中,我们想在每个Person对象中共享同一个say方法,可以这样来实现。
function Person(name, age) {
this.name = name;
this.age = age;
}//在原型对象上添加say函数,实例对象共享该函数
Person.prototype.say = function(){
console.log("say hello");
};var p = new Person("zs", 10, say);
p.say();var p2 = new Person("zs", 10, say);
p2.say();
在原型对象上添加成员的方法:
​ 构造函数.prototype.成员名 = 成员值;
为Person原型对象添加say方法后,实现了在多个实例对象上共享该方法的功能。
获取原型对象的方法:
​ 构造函数.prototype
​ 实例对象.__ proto __
在每个实例对象上都有一个__ proto 的属性,也是用来获取该对象的原型对象。
Person.prototype == p. proto __;//true
下图详细说明了各对象之间的关系:

面向对象中的核心概念
构造函数:Person,和new关键字一起创建对象
构造函数的原型对象:Person.prototype,
原型对象:和创建实例对象的构造函数相互关联的对象
实例对象:由构造器创建出来的对象称之为实例对象
实例化:由构造器创建实例对象的过程称之为实例化
对象的成员:属性+方法
实例成员:实例对象上的属性和方法,name,age,只能当前实例对象才能访问
原型成员:原型对象上的属性和方法,say(),使用该原型对象对应构造器创建出来的所有实例对象都能访问
静态成员:直接添加在构造函数上的属性和方法,只能使用构造函数才能访问
__ proto 属性介绍
该属性是在ES6之后才纳入规范,在这之前,只有部分浏览器实现。
该属性可以获取指定实例对象的原型对象,p. proto ,和Person.prototype获取的一样
我们也可以使用Object构造器上的getPrototypeOf(实例对象)方法获取指定实例对象的原型对象
以上提到的三种获取原型对象的方法所得到的结果是一样的。即:
Object.getPrototypeOf(p) == Person.prototype == p. proto __
扩展内置对象
内置对象是JS中事先定义好的对象,可以直接拿来使用的对象,在这类对象中已经封装好了一堆的方法和属性,方便开发者完成基本的功能。
但是在实际开发中,这些属性或者方法不一定能够满足我们的需求,此时就需要对这些内置对象做功能扩展。
需求:为数组对象添加一个获取元素个数的方法
var arr1 = [1, 2, 3];var arr2 = ["A", "B", "C","D"];
arr1.getLength = function () {
return this.length;
}console.log(arr1.getLength());
上面为数组arr1添加了一个getLength()方法获取其元素个数,那么此时的arr2对象上有这个方法吗?相信大家心里都有答案。如果想要arr2拥有同样的功能,也需要同样的操作。
所以这种方式不可取,如果100个数组都想都需要这样的功能,操作起来就比较复杂了。
根据前面学过的知识点,我们完全可以使用原型来解决这个问题。
var arr1 = [1, 2, 3];var arr2 = ["A", "B", "C","D"];Array.prototype.getLength = function () {
return this.length;
}console.log(arr1.getLength());// 3console.log(arr2.getLength());// 4
我们直接在Array的原型对象上添加getLength()方法,之后创建的所有的数组对象都拥有了该方法,搞定!
这种方式能够解决我们的问题,但是还是存在问题的:

在多人开发的环境中,如果使用这种方式对内置对象做扩展,可能会对其他开发人员造成影响
如果在原型对象上添加了过多的成员,会降低对象成员的搜索效率。
安全的扩展内置对象
上面扩展内置对象的方法存在一定的问题,问题的关键其实在于我们是直接在内置对象的原型上进行拓展的,这样导致对其他使用该对象的开发人员造成影响。
所以,我们的解决思路就是,自定义一个对象,让该对象继承需要扩展的内置对象,然后只需要对自定的对象进行操作即可。
function MyArray() {
}//让MyArray的原型指向Array对象//即继承Array中的所有成员
MyArray.prototype= new Array();
MyArray.prototype.getLength=function () {
return this.length;
}var arr1 = new MyArray();
arr1.push("A","B","C","D","E");//内置对象的初始方法console.log(arr1.getLength());//扩展之后的方法
接下来,如果想要对数组做扩展,我们只需要操作MyArray即可,而不需要直接操作Array,如此,就不会对其他使用Array的开发人员操作影响了。看图理解:

原型链的结构图
每个实例对象都是由构造函数创建出来的
每一个构造函数都有默认关联的原型对象
原型对象本身也是对象,所以它也有自己的构造函数
原型对象的构造函数也有默认关联的原型对象
以上就构成了一种链式访问结构,称之为原型链
下面画出了Person对象和Array对象的原型链:

以上就是我对于原型和原型链的理解,这也只是我自己的观点,如果有不合适的还请大家指出。如过有能帮助到你的地方我也会一一解答,希望我们能够共同进步。

何为JavaScript原型?读完你就明白了的更多相关文章

  1. 明白JavaScript原型链和JavaScrip继承

    原型链是JavaScript的基础性内容之一.其本质是JavaScript内部的设计逻辑. 首先看一组代码: <script type="text/javascript"&g ...

  2. 深入理解javascript原型和闭包(3)——prototype原型

    既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...

  3. 深入理解javascript原型和闭包(4)——隐式原型

    注意:本文不是javascript基础教程,如果你没有接触过原型的基本知识,应该先去了解一下,推荐看<javascript高级程序设计(第三版)>第6章:面向对象的程序设计. 上节已经提到 ...

  4. 深入理解javascript原型和闭包(6)——继承

    为何用“继承”为标题,而不用“原型链”? 原型链如果解释清楚了很容易理解,不会与常用的java/C#产生混淆.而“继承”确实常用面向对象语言中最基本的概念,但是java中的继承与javascript中 ...

  5. 深入理解javascript原型和闭包(15)——闭包

    前面提到的上下文环境和作用域的知识,除了了解这些知识之外,还是理解闭包的基础. 至于“闭包”这个词的概念的文字描述,确实不好解释,我看过很多遍,但是现在还是记不住. 但是你只需要知道应用的两种情况即可 ...

  6. javascript原型Prototype【转】

    转自:http://www.cnblogs.com/starof/p/4190404.html 在javaScript创建对象一文中提到过:用构造函数创建对象存在一个问题即同一构造函数的不同实例的相同 ...

  7. javascript 原型详解

    引:http://www.cnblogs.com/wangfupeng1988/p/3978131.html 1.什么是javascript原型 每一个函数都有prototype属性(默认生成的)和原 ...

  8. javascript原型Prototype

    在javaScript创建对象一文中提到过:用构造函数创建对象存在一个问题即同一构造函数的不同实例的相同方法是不一样的,所以我们用原型把构造函数中公共的属性和方法提取出来进行封装,达到让所有实例共享的 ...

  9. 通俗易懂的语言描述JavaScript原型

    这是一个翻译.原文地址http://javascriptissexy.com/javascript-prototype-in-plain-detailed-language/# 原型(prototyp ...

随机推荐

  1. ssh ssm ssi 服务器平台架构

    1.spring + springmvc + mybatis 使用maven构建,数据库是oracle,主要是温习mybatis配置以及与spring集成.这种框架目前是使用最广泛的,这里就不多说 2 ...

  2. 从Swift桥接文件到Clang-LLVM

    http://blog.csdn.net/u014795020/article/details/72514109 前言 今天在Swift工程中不小心创建了一个OC文件,于是乎提示我创建一个桥接文件,那 ...

  3. SPU、SKU、ARPU

    在涂涂商城开发之前,发现一篇关于电商中 SPU.SKU.ARPU 的介绍,转至博客,原文地址:http://www.ikent.me/blog/3017 什么是SPU.SKU.ARPU 首先,搞清楚商 ...

  4. Substrings SPOJ - NSUBSTR (后缀自动机)

    Substrings \[ Time Limit: 100ms\quad Memory Limit: 1572864 kB \] 题意 给出一个长度为 \(250000\) 的字符串,求出所有 \(x ...

  5. 如何保证javascript算数计算结果的精度

    前言: 我们先看如下这个js的代数计算结果,什么? 明显不是我们想要的结果3.52!! 备注:其实这个小数计算精度问题,在弱类型语言python等语言中同样存在. 问题原因之所在: JavaScrip ...

  6. [SDOI2011]染色(信息学奥赛一本通 1563)(洛谷 2486)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  7. 实现mysql的读写分离(mysql-proxy)____2

    mysql-proxy简介 MySQL读写分离是指让master处理写操作,让slave处理读操作,非常适用于读操作量比较大的场景,可减轻master的压力. 使用mysql-proxy实现mysql ...

  8. [Web] 取消Promise

    转载自 为Promise插上可取消的翅膀 const makeCancelable = (promise) => { let hasCanceled_ = false; const wrappe ...

  9. convmv 解决GBK 迁移到 UTF-8 ,中文 文件名乱码

    yum install convmv 命令: convmv -f GBK -t UTF-8 -r --nosmart --notest <目标目录> -f from -t to --nos ...

  10. maven本地仓库已经有了所需的jar包,为什么还要去请求远程仓库

    问题 IDEA 中的maven 项目,一个jar包一直导入不进来,reimport 无效.从另一仓库把这个jar包拷贝到当前仓库,还是无效.mvn clean install -e U 发现加载这个j ...