深入理解js的prototype以及prototype的一些应用
上一篇讲了js的prototype概念,在这里回顾一下prototype的定义:
prototype是函数的一个属性,并且是函数的原型对象。引用它的必然是函数,这个应该记住。
但是,很奇怪,各位看官,你有没有看过类似下面这样引用prototype的js代码:
- function func(){
- var args = Array.prototype.slice.call(arguments, 1);
- return args;
- }
咦???看着上面这行代码,你是不是对prototype只是属于函数产生深深的怀疑呢?
你明白上面那个函数的意思吗?我还是解释一下吧。
call是函数的一个方法,关于这个方法,它也是只有····函数····才能够调用的,它的作用是:调用引用它的函数。
就拿这个Array.prototype.slice.call(arguments,1)来讲,这里面包含太多信息了,我一个个分析一下。
slice(start[,end])是js的一个原生数组函数,作用是获取数组中从start下标开始到end下标结束的元素。举个例子:
- var arr1 = [2,3,'l',4,5,'j','i'];
- alert(arr1.slice(1));//结束下标省略表示从开始下标截取到末尾
- //这里alert的是3,'l',4,5,'j','i',你自己可以试一下
arguments是js函数对象的一个属性,作用是获取函数的实参,返回的是一个以函数实参为属性元素的对象。举个例子:
- function args(){
- return this.arguments;//这里的this可以省略,你自己可以试一下
- //我加上是为了说明,调用arguments的只能是对象
- }
- alert(JSON.stringify(args(1,3,5,6,8)));
- //返回的是{"0":"1","1":"3","2":"5","3":"6","4":"8"}
关于函数的对象属性arguments这里就讲这么多了,要详细理解,可以百度。
而Array是js中生成数组的关键字。
这里为什么要用Array.prototype来调用slice函数呢?而不用Array.slice,原因很简单,因为数组的关键字Array不能这样子Array.xx直接调用js的数组函数。但为什么不能直接这样调用呢?不急,下面我们来做实验,你就会很清楚了。
- alert(Array.slice());
- //Uncaught TypeError: Array.slice is not a function
这里直接给你报错了,说明了什么?呵呵,这说明Array关键字确实不能直接调用数组的函数。
- alert(JSON.stringify(Array.prototype));
- alert(JSON.stringify(Array.prototype.slice()));
这里返回都是空数组···[]···,说明了什么?说明了Array关键字确实是可以调用prototype函数的属性的,同时也说明js是可以这样子Array.prototype调用js的数组函数的。
说到这里,问题就来了,我上面不是说,prototype是js函数的一个属性,只能被函数调用吗?怎么这里Array关键字可以调用这个属性prototype呢?那么,我这不是坑自己对prototype的定义是错误的吗?我这不是给自己打脸吗?哎,看官,没错,你这里看到的都是正确的。可是,至于Array关键字可以调用函数的prototype属性,我有没有给自己打脸,这里,我们先别急得下结论。
转个弯说,看官是否还记得js生成数组的几种方式?应该有多种,但,我这里就不介绍了。
不过,你是否看过这样生成数组的方式?我们先来看下面的代码:
- var arr = new Array();
这个方式生成数组还记得吧?那么,我们js的function是不是也可以像下面这样子生成对象呢?
- function func(){
- }
- var obj = new func();
上面生成数组的方式和下面构造函数生成对象的方式是不是很相似?没错,js中function和Array都是可以通过new来生成对象这样的东西,这说明了什么呢?你看Array()和func()是不是很像?是不是最后面都有一对圆括号?是就对了,呵呵,说了这么多,我只是想揭露一样东西,这个东西就是,假如我猜的的没有错的话,Array()这个东西其实是js一个·····构造数组的内置函数····,不然,可以用new Array()的方式生存数组的方式就说不过去了是吧?
讲到这里,我们再返回来说js可以这样子Array.prototype调用prototype就很明白不过了是吧?Array()是js的一个内置函数,既然Array是一个函数,那么Array肯定拥有prototype这个属性对吧?所以说,Array关键字调用prototype并没有违反prototype是函数的一个属性这个原则,prototype是函数的一个属性依然是一个不变的结论。
关于Array生成数组的方式,类似的我们是否可以这样子new Object()生成对象,或者new String()这样子生成字符串?既然可以这样子构造对象和字符串,那么我们下面的代码也应该是可行的,对吧?
- alert(JSON.stringify(String.prototype));
- alert(JSON.stringify(Object.prototype));
根据上面的解释,你应该知道这里是可以执行的吧?你应该知道这里的之所以能执行的原理吧?你自己试试。这里就不再解释了。
讲到这里,哎,我既然把行文开始的那个函数给忘了?这里讲解一下本文开始那个func函数的作用:
func函数的作用就是,从第二个实参数开始获取func函数的实参。
我来给你分析一下:
- function func(){
- var args = Array.prototype.slice.call(arguments, 1);
- return args;
- }
- alert(func(0,1,2,3,4));//给func函数传实参
Array.prototype是一个空数组,
Array.prototype.slice()的意思是一个空数组调用数组的函数slice(),
Array.prototype.slice.call()的意思是call函数调用数组的函数slice(),
这里call()怎么调用slice()呢?
是这样子的,Arguments获取func函数实参列表,生成一个对象传递给call()函数,call函数又把Arguments生成的对象传递给Array.prototype这个空数组,把第二个参数···1···传递给slice函数,然后,call就让引用它的函数slice执行slice(1),所以slice就从1下标开始获取数组的元素了,而这个数组的元素其实就是Arguments的元素,因此,这个函数func的作用就是获取下标为1开始的所有实参。不相信,你自己可以执行一下上面的函数。
下面讲讲prototype的应用:
应用1:
给原型对象增加函数,就是让对象拥有公用的函数。
例子:我给数组原型对象增加一个打乱数组方法:
- //给数组原型增加一个打乱数组的函数
- Array.prototype.shuffle=function(){
- var value = this.valueOf(),len = this.length,temp,key;
- while(len--){
- //随机生成数组的下标
- key = Math.floor(Math.random()*len);
- //temp为中间交换变量
- temp = value[key];
- value[key] = value[len];
- value[len] = temp;
- }
- return value;
- }
- var arr1 = [0,1,2,3,4,5,6,7,8,9];
- var arr2 = ['a','b','c','d','e','f'];
- alert(JSON.stringify(arr1.shuffle()));
- alert(JSON.stringify(arr2.shuffle()));
你可以尝试着再增加一个数组arr3看看它能不能调用shuffle函数,因为我这里是给Array的原型对象增加的函数,所以在这个脚本内,所有数组都拥有shuffle这个函数。
应用2:
给原型对象增加属性,也就是给对象增加公用的属性
例子:
- function fun(){
- }
- fun.prototype.name = '小东';
- fun.prototype.arr = [1,2,3,4];//这里的属性可以是数组,也可以是对象
- var ob1 = new fun();
- var ob2 = new fun();
- alert(JSON.stringify(ob1.name));
- alert(JSON.stringify(ob2.arr));
应用3:
实现原型继承;
- function P1(){
- }
- function P2(){
- }
- //原型对象增加属性和方法
- P2.prototype.name = 'P2"s name';
- P2.prototype.get=function(value){
- return value;
- }
- //实例化P2构造函数的一个对象
- var obp2 = new P2();//这个对象应该包含所有原型对象的属性和方法
- //给P1的原型对象赋值一个对象,相当于P1继承了obp2的所有属性和方法
- P1.prototype = obp2;//这个式子,简单来讲就类似于a = b, b赋值给a这个总该明白吧?
- //调用P1从obp2继承过来的get函数
- alert(P1.prototype.get('out"s name'));
- //展示P1从obp2继承过来的name属性
- alert(P1.prototype.name);
- //用构造函数P1实例化一个obp1对象
- var obp1 = new P1();
- //P1的原型对象prototype既然已经继承了obp2的所有属性和函数,那么依据P1所实例化出来的对象也都有obp2的属性和函数了
- alert(obp1.get('obp1"s name'));
关于prototype就讲到这里,假如本文有什么错误,还望各位看官指出,我好纠正。
特别指出:
Array.prototype是一个数组
String.prototype是一个字符串
Object.prototype是一个对象
深入理解js的prototype以及prototype的一些应用的更多相关文章
- 理解js中__proto__和prototype的区别和关系
首先,要明确几个点:1.在JS里,万物皆对象.方法(Function)是对象,方法的原型(Function.prototype)是对象.因此,它们都会具有对象共有的特点.即:对象具有属性__proto ...
- 简单理解js的prototype属性
在进入正文之前,我得先说说我认识js的prototype这个东西的曲折过程. 百度js的prototype的文章,先看看,W3School关于prototype的介绍: 你觉得这概念适合定义js的pr ...
- 深入理解js——prototype原型
之前(深入理解js--一切皆是对象)中说道,函数也是一种对象.它也是属性的集合,你也可以对函数进行自定义属性.而JavaScript默认的给了函数一个属性--prototype(原型).每个函数都有一 ...
- 【学习笔记】深入理解js原型和闭包(3)——prototype原型
既typeof之后的另一位老朋友! prototype也是我们的老朋友,即使不了解的人,也应该都听过它的大名.如果它还是您的新朋友,我估计您也是javascript的新朋友. 在咱们的第一节(深入理解 ...
- 理解js中的原型链,prototype与__proto__的关系
说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script type="text/javascript"> 2 var Pers ...
- 转载-对js中new、prototype的理解
说明:本篇文章是搜集了数家之言,综合的结果,应向数家致谢 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: <script type="text/java ...
- 【转】理解js中的原型链,prototype与__proto__的关系
说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script type="text/javascript"> 2 var Pers ...
- 关于js中__proto__和prototype的一些理解<转>
var Person = function(name) { this.name = name; } var p = new Person(); new操作符的操作是 var p = {} p. ...
- [转]理解js中的原型链,prototype与__proto__的关系
本文转自:http://rockyuse.iteye.com/blog/1426510 说到prototype,就不得不先说下new的过程. 我们先看看这样一段代码: 1 <script typ ...
随机推荐
- Power BI for Office 365(四)Power View第一部分
Power View是一种可以创建动态的交互式报表的工具,并且支持丰富多样的图表类型,在Power View中创建的报表可以很容易地进行分享,以及供查看报表的用户对Power View报表进行交互.从 ...
- WPF使用IDataErrorInfo进行数据校验
这篇博客将介绍如何使用IDataErrorInfo进行数据校验.下面直接看例子.一个Customer类,两个属性(FirstName, Age) class Customer { public str ...
- iOS APP提交上架最新流程(转)
时隔1年又让我鼓捣iOS,刚接手就是上架,经验值为0的我,虽然内心是拒绝的,但还是要接受这项任务滴!也就是在被拒后重新审核,再改在提交...这样 反复的过程中也对上架流程熟悉了好多,写篇帖子送给同为菜 ...
- EXT.NET 使用总结(1)
前言 从系统改版到现在,将近半年的时间,原本陌生的Ext.NET的UI框架,也慢慢的熟悉了.总的来说,这个UI框架还是很优秀的,但是也没有100%完美的产品(老系统使用easy ui其实也挺好的).趁 ...
- 【Mybatis高级映射】一对一映射、一对多映射、多对多映射
前言 当我们学习heribnate的时候,也就是SSH框架的网上商城的时候,我们就学习过它对应的高级映射,一对一映射,一对多映射,多对多映射.对于SSM的Mybatis来说,肯定也是差不多的.既然开了 ...
- Android Studio 在mac下对应的快捷键
Mac下快捷键的符号所对应的按键⌥-> option|alt⇧->shift⌃->control⌘->command⎋->esc注: 与F6/F7/F12等F功能键开头的 ...
- MT4平台经验总结
https://www.mql5.com/zh/code/8462 https://www.mql5.com/zh/code/8074 https://www.mql5.com/zh/code/787 ...
- WIN32/API/SDK/MFC四者之间的联系和区别
上面大家都说Win32是一个子系统,这个当然是对的,不过我们有时候我们所说Win32通俗的就是指32位的Windows系统,从 windows95/98到NT/2000/XP都是32位Windows. ...
- iOS 设置1像素的UIView线
如果是代码实现,直接 在CGRectMake里把对应的参数设置为: 1.0/[UIScreenmainScreen].scale 即可. 如果是用xib实现,就需要将对应的限制拖一个I ...
- Pig语言基础-【持续更新中】
***本文参考了Pig官方文档以及已有的一些博客,并加上了自己的一些知识性的理解.目前正在持续更新中.*** Pig作为一种处理大规模数据的高级查询语言,底层是转换成MapReduce实现的, ...