在现在的业务开发中,应该很少人在写原生JavaScript了,大家都一股脑地扑在各个框架上。本来,这些框架对于业务和开发者来说是一种福音,减少了各种各样的开发痛点,但是带来的负面问题就是对于开发者来说,越来越依赖框架,离原生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()方法,之后创建的所有的数组对象都拥有了该方法,搞定!
这种方式能够解决我们的问题,但是还是存在问题的:

  1. 在多人开发的环境中,如果使用这种方式对内置对象做扩展,可能会对其他开发人员造成影响
  2. 如果在原型对象上添加了过多的成员,会降低对象成员的搜索效率。

安全的扩展内置对象

上面扩展内置对象的方法存在一定的问题,问题的关键其实在于我们是直接在内置对象的原型上进行拓展的,这样导致对其他使用该对象的开发人员造成影响。
所以,我们的解决思路就是,自定义一个对象,让该对象继承需要扩展的内置对象,然后只需要对自定的对象进行操作即可。

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对象的原型链:


今天关于JS中原型和原型链的内容就先进行到这里。大家有什么疑问,可以在评论区评论。或者在JS方面有什么需要了解的也请大家积极评论。希望大家可以相互分享工作和学习中的知识和见识。

如何理解JavaScript的原型和原型链的更多相关文章

  1. 【JavaScript】深入理解JavaScript之强大的原型和原型链

    由于JavaScript是唯一一个被广泛使用的基于原型继承的语言,所以理解两种继承模式的差异是需要一定时间的,今天我们就来了解一下原型和原型链. AD: hasOwnProperty函数: hasOw ...

  2. 深入理解Javascript中构造函数和原型对象的区别

    在 Javascript中prototype属性的详解 这篇文章中,详细介绍了构造函数的缺点以及原型(prototype),原型链(prototype chain),构造函数(constructor) ...

  3. 深入理解Javascript中构造函数和原型对象的区别(转存)

    Object是构造函数,而Object.prototype是构造函数的原型对象.构造函数自身的属性和方法无法被共享,而原型对象的属性和方法可以被所有实例对象所共享. 首先,我们知道,构造函数是生成对象 ...

  4. 理解Javascript的动态语言特性

    原文:理解Javascript的动态语言特性 理解Javascript的动态语言特性 Javascript是一种解释性语言,而并非编译性,它不能编译成二进制文件. 理解动态执行与闭包的概念 动态执行: ...

  5. 深入理解javascript原型和闭包(14)——从【自由变量】到【作用域链】

    先解释一下什么是“自由变量”. 在A作用域中使用的变量x,却没有在A作用域中声明(即在其他作用域中声明的),对于A作用域来说,x就是一个自由变量.如下图 如上程序中,在调用fn()函数时,函数体中第6 ...

  6. <深入理解JavaScript>学习笔记(5)_强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. (prototypal :原型.学好英语还是很重要的) 虽然这经常被当作是 JavaScript 的缺点 ...

  7. 深入理解javascript原型链

    在javascript中原型和原型链是一个很神奇的东西,对于大多数人也是最难理解的一部分,掌握原型和原型链的本质是javascript进阶的重要一环.今天我分享一下我对javascript原型和原型链 ...

  8. 深入理解JavaScript系列(5):强大的原型和原型链

    前言 JavaScript 不包含传统的类继承模型,而是使用 prototypal 原型模型. 虽然这经常被当作是 JavaScript 的缺点被提及,其实基于原型的继承模型比传统的类继承还要强大.实 ...

  9. javascript系列--认识并理解构造函数,原型和原型链

    一.前言 介绍构造函数,原型,原型链.比如说经常会被问道:symbol是不是构造函数:constructor属性是否只读:prototype.[[Prototype]]和__proto__的区别:什么 ...

随机推荐

  1. WHAT IS GAME-BASED LEARNING?

    https://www.growthengineering.co.uk/what-is-game-based-learning/ Gamification and game-based learnin ...

  2. python--面向对象编程之学生选课系统练习

    1.系统目录结构 文件夹注解: bin--系统管理员和学生的主程序代码 config--系统的配置文件 db--系统的数据文件 admin--管理员的数据文件 student--学生的数据文件 lib ...

  3. Vuejs组件基础

    一.概念 ①组件就是对局部视图的封装,组件思想就是把一个很大的复杂的 Web 页面视图给拆分成一块一块的组件视图,然后利用某种特定的方式把它们组织到一起完成完整的 Web 应用构建. ②目前主流的前端 ...

  4. rsync同步备份

    一.服务器端.备份客户端安装 rsync 服务. 1.环境: CentOS 主 IP:172.16.3.18 备 IP:172.16.3.19 2.安装 rsync 软件 #yum install r ...

  5. MSSQL复制表数据及表结构

    目标表存在: insert into 目标表 select * from 原表 目标表不存在: select * into 目标表 from 原表 复制表结构 select * into 目标表 fr ...

  6. opener和parent的区别

    openeropener用于在window.open的页面引用执行该window.open方法的的页面的对象.例如:A页面通过window.open()方法弹出了B页面,在B页面中就可以通过opene ...

  7. idea中如何

    idea工具maven projects里面有9种生命周期,生命周期是包含在一个项目构建中的一系列有序的阶段. 一.最常用的两种打包方法: 1.clean,package(如果报错,很可能就是jar依 ...

  8. 【spring源码学习】spring的事务管理源码学习

    一.抽象概念 1.事务管理器 接口:org.springframework.transaction.PlatformTransactionManager 实现类:org.springframework ...

  9. Curator框架实现ZooKeeper分布式锁

    排他锁(X) 这里主要讲讲分布式锁中的排他锁.排他锁(Exclusive Locks,简称X锁),又称为写锁或独占锁,是一种基本的锁类型.如果事务T1对数据对象O1加上了排他锁,那么在整个加锁期间,只 ...

  10. linux删除文件的前n行

    需求描述: 今天看了一个系统的临时文件,有5.6G的大小,这个文件也没有用了,想要将大部分的文件都删除掉. 在此记录下删除的过程.删除前n行的记录. 操作过程: 对于数据量比较大的情况(本例5800万 ...