上一篇讲了js的prototype概念,在这里回顾一下prototype的定义:数组
prototype是函数的一个属性,而且是函数的原型对象。引用它的必然是函数,这个应该记住。dom
可是,很奇怪,各位看官,你有没有看过相似下面这样引用prototype的js代码:函数
function func(){ var args = Array.prototype.slice.call(arguments, 1); return args; }
咦???看着上面这行代码,你是否是对prototype只是属于函数产生深深的怀疑呢?this
你明白上面那个函数的意思吗?我仍是解释一下吧。spa
call是函数的一个方法,关于这个方法,它也是只有····函数····才可以调用的,它的做用是:调用引用它的函数。prototype
就拿这个Array.prototype.slice.call(arguments,1)来说,这里面包含太多信息了,我一个个分析一下。code
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函数对象的一个属性,做用是获取函数的实参,返回的是一个以函数实参为属性元素的对象。举个例子:blog
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是一个对象