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 相关文章推荐
用JQuery 实现的自定义对话框
Mar 24 Javascript
Extjs学习笔记之八 继承和事件基础
Jan 08 Javascript
js中的值类型和引用类型小结 文字说明与实例
Dec 12 Javascript
jquery click([data],fn)使用方法实例介绍
Jul 08 Javascript
js实现对ajax请求面向对象的封装
Jan 08 Javascript
jQuery Validate表单验证插件 添加class属性形式的校验
Jan 18 Javascript
JS创建对象的写法示例
Nov 04 Javascript
JS出现失效的情况总结
Jan 20 Javascript
详解vue-cli 接口代理配置
Dec 13 Javascript
layui上传图片到服务器的非项目目录下的方法
Sep 26 Javascript
文章或博客自动生成章节目录索引(支持三级)的实现代码
May 10 Javascript
koa中间件核心(koa-compose)源码解读分析
Jun 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
DedeCms模板安装/制作概述
2007/03/11 PHP
求PHP数组最大值,最小值的代码
2011/10/31 PHP
一组PHP可逆加密解密算法实例代码
2014/01/21 PHP
详解PHP中的序列化、反序列化操作
2017/03/21 PHP
laravel实现Auth认证,登录、注册后的页面回跳方法
2019/09/30 PHP
jQuery Ajax文件上传(php)
2009/06/16 Javascript
javascript event 事件解析
2011/01/31 Javascript
JS 控制小数位数的实现代码
2011/08/02 Javascript
js 控制图片大小核心讲解
2013/10/09 Javascript
node.js中的console.info方法使用说明
2014/12/09 Javascript
jquery实现的判断倒计时是否结束代码
2016/02/05 Javascript
jQuery购物车插件jsorder用法(支持后台处理程序直接转换成DataTable处理)
2016/06/08 Javascript
JS作为值的函数用法示例
2016/06/20 Javascript
bootstrapfileinput实现文件自动上传
2016/11/08 Javascript
JavaScript中定义对象原型的两种使用方法
2016/12/15 Javascript
微信小程序 自动登陆PHP源码实例(源码下载)
2017/05/08 Javascript
jQuery获取随机颜色的实例代码
2018/05/21 jQuery
详解Vue项目引入CreateJS的方法(亲测可用)
2019/05/30 Javascript
[47:12]TFT vs Secret Supermajor小组赛C组 BO3 第三场 6.3
2018/06/04 DOTA
python使用wmi模块获取windows下硬盘信息的方法
2015/05/15 Python
使用Python编写一个最基础的代码解释器的要点解析
2016/07/12 Python
Python PyAutoGUI模块控制鼠标和键盘实现自动化任务详解
2018/09/04 Python
python 解决动态的定义变量名,并给其赋值的方法(大数据处理)
2018/11/10 Python
树莓派用python中的OpenCV输出USB摄像头画面
2019/06/22 Python
Python模块的定义,模块的导入,__name__用法实例分析
2020/01/07 Python
Python实现病毒仿真器的方法示例(附demo)
2020/02/19 Python
python pandas.DataFrame.loc函数使用详解
2020/03/26 Python
python 输入字符串生成所有有效的IP地址(LeetCode 93号题)
2020/10/15 Python
Html5新特性用canvas标签画多条直线附效果截图
2014/06/30 HTML / CSS
波兰汽车配件网上商店:iParts.pl
2020/09/08 全球购物
汽车装潢店创业计划书范文
2014/02/05 职场文书
《搭石》教学反思
2014/04/07 职场文书
工商局副局长个人对照检查材料
2014/09/25 职场文书
信息技术研修心得体会
2016/01/08 职场文书
《认识年月日》教学反思
2016/02/19 职场文书
Python入门学习之类的相关知识总结
2021/05/25 Python