您当前的位置:首页 > 电脑百科 > 程序开发 > 语言 > javascript

JavaScript原型详解

时间:2019-12-03 16:54:08  来源:  作者:

1,前言

下面是2008年Github创建以来,各种编程语言的排名情况

JavaScript原型详解

 

排名

其中JAVAScript自2013年之后就盘踞第一名,成为github上被使用最多的语言,早期,JS的使用还主要集中于浏览器中,但是随着node.js进军服务器开发和React Native逐渐向移动端渗透,一个属于JS的全栈时代就要来临了。而且JS界还流传一句名言:“所有能用JS开发的应用程序,最终都会用JS来开发”。我就问你怕不怕?好了,说了这么多,我并不是想说JS为世界上最好的语言(显然php才是,对吧?←_←),也不是觉得JS会替代谁,我只是觉得,JavaScript将会是一个大家(不止web端)都应该了解和学习的语言工具。

2,面对对象(OOP)

2.1 实现思路

面对对象是大家都很熟悉的程序设计思想,是对真实世界的抽象,目前主要OOP语言用来实现面对对象的基础是类,通过类的封装,继承来映射真实世界。包括Java,C#,甚至是Python等都通过类的设计来实现面对对象。但是细想起来也会觉得有问题,因为真实世界其实没有类这种概念,只有一个个不同的对象,真实世界中,继承关系发生在对象和对象之间,而不是类。就比如孩子是对象,父母也是对象,孩子(对象)继承自父母(对象)

JS也是面对对象的编程语言,只不过它实现面对对象的思路是基于原型(prototype),而不是类。这种思路也叫对象关联(Object Link Other Object),即在对象上直接映射那种真实世界的关系(如继承)。

2.2 原型概念

相关的概念其实我研究了好几天,除开原型概念本身,与之联系的对象的产生,构造函数,proto,prototype的区别,为什么对象没有prototype这个指向原型的属性,而是使用proto来指向原型?

好,我们先来谈谈原型这个概念。JS中一切皆对象,而每个对象都有一个原型(Object除外),这个原型,大概就像Java中的父类,所以,基本上你可以认为原型就是这个对象的父对象,即每一个对象(Object除外)内部都保存了它自己的父对象,这个父对象就是原型。一般创建的对象如果没有特别指定原型,那么它的原型就是Object(这就很类似Java中所有的类默认继承自Object类)。

2.3 对象创建

在JS中,对象创建的方法有很多种,最常见的如下:

//第一种,手动创建
var a={'name':'lala'}; 
//第二种,构造函数
function A(){
 this.name='lala';
}
var a=new A();
//第三种,class (ES6标准写法)
class A{
 constructor(){
 //super();此处没有使用extends显式继承,不可使用super()
 this.name='lala';
 }
}
var a=new A()
//其实后面两种方法本质上是一种写法复制代码

这三种写法创建的对象的原型(父对象)都是Object,需要提到的是,ES6通过引入class ,extends等关键字,以一种语法糖的形式把构造函数包装成类的概念,更便于大家理解。是希望开发者不再花精力去关注原型以及原型链,也充分说明原型的设计意图和类是一样的。

2.3 查看对象原型

当对象被创建之后,查看它们的原型的方法不止一种,以前一般使用对象的proto属性,ES6推出后,推荐用Object.getPrototypeOf()方法来获取对象的原型

function A(){
 this.name='lala';
}
var a=new A();
console.log(a.__proto__) 
//输出:Object {}
//推荐使用这种方式获取对象的原型
console.log(Object.getPrototypeOf(a)) 
//输出:Object {}复制代码

无论对象是如何创建的,默认原型都是Object,在这里需要提及的比较特殊的一点就是,通过构造函数来创建对象,函数A本身也是一个对象,而A有两个指向表示原型的属性,分别是proto和prototype,而且两个属性并不相同

function A(){
 this.name='lala';
}
var a=new A();
console.log(A.prototype) 
//输出:Object {}
console.log(A.__proto__) 
//输出:function () {}
console.log(Object.getPrototypeOf(A))
//输出:function () {}复制代码

函数的的prototype属性只有在当作构造函数创建的时候,把自身的prototype属性值赋给对象的原型。而实际上,作为函数本身,它的原型应该是function对象,然后function对象的原型才是Object。

总之,建议使用ES6推荐的查看原型和设置原型的方法。

2.4 原型的用法

其实原型和类的继承的用法是一致的:当你想用某个对象的属性时,将当前对象的原型指向该对象,你就拥有了该对象的使用权了。

function A(){
 this.name='world ';
}
function B(){
 this.bb="hello"
 }
var a=new A();
var b=new B();
Object.setPrototypeOf(a,b);
//将b设置为a的原型,此处有一个问题,即a的constructor也指向了B构造函数,可能需要纠正
a.constructor=A;
console.log(a.bb)
//输出 hello复制代码

(增补)

如果使用ES6来做的话则简单许多,甚至不涉及到prototype这个属性

class B{
 constructor(){
 this.bb='hello'
 }
}
class A extends B{
 constructor(){
 super()
 this.name='world'
 }
}
var a=new A();
console.log(a.bb+" "+a.name);
//输出hello world
console.log(typeof(A))
//输出 "function"复制代码

怎么样?是不是已经完全看不到原型的影子了?活脱脱就是类继承,但是你也看得到实际上类A 的类型是function,所以说,本质上class在JS中是一种语法糖,JS继承的本质依然是原型,不过,ES6引入class,extends 来掩盖原型的概念也是一个很友好的举动,对于长期学习那些类继承为基础的面对对象编程语言的程序员而言。

我的建议是,尽可能理解原型,尽可能用class这种语法糖。


2.5 原型链

这个概念其实也变得比较简单,可以类比类的继承链条,即每个对象的原型往上追溯,一直到Object为止,这组成了一个链条,将其中的对象串联起来,当查找当前对象的属性时,如果没找到,就会沿着这个链条去查找,一直到Object,如果还没发现,就会报undefined。那么也就意味着你的原型链不能太长,否则会出现效率问题。

3,总结

  • 对于原型概念的理解
  • 类比类的继承,对象的原型可以理解为对象的父对象
  • 原型的运用
  • 尽可能使用ES6的标准,使用class,extends,Object.getPrototype(),Object.setPrototype()等等
  • 需要注意的点
  • 原型继承链条不要太长
  • 指定原型时,注意constructor也会改变。

4,后记(增补)

还有人觉得我的分析很抽象,所以,我再总结一下,如果要一句话理解JS中的原型是什么,那就是,对象的原型就指的对象的父对象。每个对象都有父对象,父对象本身也有父对象(爷对象?)。而原型链呢,很像过去家谱的概念,可以从你往上追溯你父亲,到爷爷,到太爷爷一直到头,这就形成了一个链条,如果其中每个人都比作一个对象,那么这个链条就是原型链。



Tags:JavaScript   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === 'a') { b = true} else { b = false}// goodb = a === 'a'2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Tags: JavaScript  点击:(6)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  Tags: JavaScript  点击:(20)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Tags: JavaScript  点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  Tags: JavaScript  点击:(35)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  Tags: JavaScript  点击:(40)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== '') { let username = username1; }优化后...【详细内容】
2021-10-28  Tags: JavaScript  点击:(51)  评论:(0)  加入收藏
1、前言async函数,也就是我们常说的async/await,是在ES2017(ES8)引入的新特性,主要目的是为了简化使用基于Promise的API时所需的语法。async和await关键字让我们可以用一种更简...【详细内容】
2021-09-17  Tags: JavaScript  点击:(61)  评论:(0)  加入收藏
为什么要使用 debugger这篇文章将介绍如何使用断点来进行 JavaScript 调试。在读这篇文章之前,需要问一个问题:为什么要使用断点来进行调试?我们首先需要认可使用断点的是必要...【详细内容】
2021-08-26  Tags: JavaScript  点击:(66)  评论:(0)  加入收藏
JavaScript 可以做很多好玩的事, 从复杂的框架到处理API,有太多的东西需要学习。但是,它也能让我们只用一行就能做一些了不起的事情。1. 获得一个随机的布尔值(true/false)该函数...【详细内容】
2021-08-19  Tags: JavaScript  点击:(77)  评论:(0)  加入收藏
JavaScript 提供了大量不同的处理数组的方法,这里花几分钟时间介绍 8 个项目中可以用到的数组方法。1. Array.map()使用.map() 方法,可以创建一个基于原始数组的修订版数组。....【详细内容】
2021-08-19  Tags: JavaScript  点击:(95)  评论:(0)  加入收藏
▌简易百科推荐
1、通过条件判断给变量赋值布尔值的正确姿势// badif (a === 'a') { b = true} else { b = false}// goodb = a === 'a'2、在if中判断数组长度不为零...【详细内容】
2021-12-24  Mason程    Tags:JavaScript   点击:(6)  评论:(0)  加入收藏
给新手朋友分享我收藏的前端必备javascript已经写好的封装好的方法函数,直接可用。方法函数总计:41个;以下给大家介绍有35个,需要整体文档的朋友私信我,1、输入一个值,将其返回数...【详细内容】
2021-12-15  未来讲IT    Tags:JavaScript   点击:(20)  评论:(0)  加入收藏
1. 检测一个对象是不是纯对象,检测数据类型// 检测数据类型的方法封装(function () { var getProto = Object.getPrototypeOf; // 获取实列的原型对象。 var class2type =...【详细内容】
2021-12-08  前端明明    Tags:js   点击:(23)  评论:(0)  加入收藏
作者:一川来源:前端万有引力 1 写在前面Javascript中的apply、call、bind方法是前端代码开发中相当重要的概念,并且与this的指向密切相关。本篇文章我们将深入探讨这个关键词的...【详细内容】
2021-12-06  Nodejs开发    Tags:Javascript   点击:(19)  评论:(0)  加入收藏
概述DOM全称Document Object Model,即文档对象模型。是HTML和XML文档的编程接口,DOM将文档(HTML或XML)描绘成一个多节点构成的结构。使用JavaScript可以改变文档的结构、样式和...【详细内容】
2021-11-16  海人为记    Tags:DOM模型   点击:(35)  评论:(0)  加入收藏
入口函数 /*js加载完成事件*/ window.onload=function(){ console.log("页面和资源完全加载完毕"); } /*jQuery的ready函数*/ $(document).ready(function(){ co...【详细内容】
2021-11-12  codercyh的开发日记    Tags:jQuery   点击:(36)  评论:(0)  加入收藏
一、判断是否IE浏览器(支持判断IE11与edge)function IEVersion() {var userAgent = navigator.userAgent; //取得浏览器的userAgent字符串var isIE = userAgent.indexOf("comp...【详细内容】
2021-11-02  V面包V    Tags:Javascript   点击:(40)  评论:(0)  加入收藏
Null、Undefined、空检查普通写法: if (username1 !== null || username1 !== undefined || username1 !== '') { let username = username1; }优化后...【详细内容】
2021-10-28  前端掘金    Tags:JavaScript   点击:(51)  评论:(0)  加入收藏
今天我们将尝试下花 1 分钟的时间简单地了解下什么是 JS 代理对象(proxies)?我们可以这样理解,JS 代理就相当于在对象的外层加了一层拦截,在拦截方法里我们可以自定义一些个性化...【详细内容】
2021-10-18  前端达人    Tags:JS   点击:(51)  评论:(0)  加入收藏
带有多个条件的 if 语句把多个值放在一个数组中,然后调用数组的 includes 方法。// bad if (x === "abc" || x === "def" || x === "ghi" || x === "jkl") { //logic } // be...【详细内容】
2021-09-27  羲和时代    Tags:JS   点击:(58)  评论:(0)  加入收藏
最新更新
栏目热门
栏目头条