js prototype深入理解及应用实例分析


Posted in Javascript onNovember 25, 2019

本文实例讲述了js 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是一个对象

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
超级兔子让浮动层消失的前因后果
Mar 09 Javascript
UpdatePanel和Jquery冲突的解决方法
Apr 01 Javascript
JavaScript解析URL参数示例代码
Aug 12 Javascript
jquery动画效果学习笔记(8种效果)
Nov 13 Javascript
JS获取数组最大值、最小值及长度的方法
Nov 24 Javascript
多功能jQuery树插件zTree实现权限列表简单实例
Jul 12 Javascript
Json按某个键的值进行排序
Dec 22 Javascript
JS实现的四级密码强度检测功能示例
May 11 Javascript
jQuery 实现左右两侧菜单添加、移除功能
Jan 02 jQuery
JS实现移动端触屏拖拽功能
Jul 31 Javascript
vue实现移动端轻量日期组件不依赖第三方库的方法
Apr 28 Javascript
关于javascript中的promise的用法和注意事项(推荐)
Jan 15 Javascript
KnockoutJS数组比较算法实例详解
Nov 25 #Javascript
js实现简单的日历显示效果函数示例
Nov 25 #Javascript
VUE.CLI4.0配置多页面入口的实现
Nov 25 #Javascript
用Golang运行JavaScript的实现示例
Nov 25 #Javascript
JS插入排序简单理解与实现方法分析
Nov 25 #Javascript
纯 JS 实现放大缩小拖拽功能(完整代码)
Nov 25 #Javascript
python实现迭代法求方程组的根过程解析
Nov 25 #Javascript
You might like
phpmyadmin导入(import)文件限制的解决办法
2009/12/11 PHP
关于php mvc开发模式的感想
2011/06/28 PHP
php+xml实现在线英文词典查询的方法
2015/01/23 PHP
php检查字符串中是否包含7位GSM字符的方法
2015/03/17 PHP
Yii的Srbac插件用法详解
2016/07/14 PHP
Laravel 5.3 学习笔记之 安装
2016/08/28 PHP
javascript 获取图片颜色
2009/04/05 Javascript
Javascript的构造函数和constructor属性
2010/01/09 Javascript
js关闭子窗体刷新父窗体实现方法
2012/12/04 Javascript
JavaScript—window对象使用示例
2013/12/09 Javascript
javascript使用百度地图api和html5特性获取浏览器位置
2014/01/10 Javascript
JavaScript学习笔记之定时器
2015/01/22 Javascript
JS实现为表格动态添加标题的方法
2015/03/31 Javascript
javascript实现根据时间段显示问候语的方法
2015/06/18 Javascript
javascript实现连续赋值
2015/08/10 Javascript
js支持键盘控制的左右切换立体式图片轮播效果代码分享
2015/08/26 Javascript
深入浅析JavaScript面向对象和原型函数
2016/02/06 Javascript
jquery 点击元素后,滚动条滚动至该元素位置的方法
2016/08/05 Javascript
轮播图组件js代码
2016/08/08 Javascript
React 全自动数据表格组件——BodeGrid的实现思路
2019/06/12 Javascript
JavaScript实现移动端带transition动画的轮播效果
2020/03/24 Javascript
详解JS深拷贝与浅拷贝
2020/08/04 Javascript
python类参数self使用示例
2014/02/17 Python
Python数据结构dict常用操作代码实例
2020/03/12 Python
爱游人:Travelliker
2017/09/05 全球购物
NFL欧洲商店(德国):NFL Europe Shop DE
2018/11/03 全球购物
Laura Geller官网:美国彩妆品牌
2018/12/29 全球购物
DeinDesign德国:设计自己的手机壳
2019/12/14 全球购物
办公室保洁员岗位职责
2013/12/02 职场文书
酒店总经理欢迎词
2014/01/15 职场文书
《圆明园的毁灭》教学反思
2014/02/28 职场文书
简历中个人自我评价分享
2014/03/15 职场文书
《长相思》听课反思
2014/04/10 职场文书
2015年秋季开学典礼校长致辞
2015/07/16 职场文书
小学同学聚会感言
2015/07/30 职场文书
JavaScript使用canvas绘制坐标和线
2021/04/28 Javascript