Array length:你问我有多长? 数组的长度是一个可修改的属性,而作为一个类数组的必要条件也是具有一个可以读写的length
属性。
var arr = [1 ,2 ,3 ,4 ,5 ];
console .log( arr.length );
arr.length = 6 ;
console .log( arr );
arr.length = 4 ;
console .log (arr);
console .log(arr[arr.lentgh-1 ]);
利用length的特征(可读写),以及数组元素的可枚举性,我们来伪造一个伪数组:
var FakeArr = function ( ) {}
Object .defineProperty(FakeArr.prototype, 'length' , {
writable : true ,
value: 5
});
var fakeArr = new FakeArr();
for (var i = 0 ; i < 5 ; i++) {
fakeArr[i] = i;
}
[].push.call(fakeArr,5 );
for ( i=0 , length = fakeArr.length; i<length; i++ ){
console .log(fakeArr[i]);
}
console .log (fakeArr);
[object Object] {
0: 0,
1: 1,
2: 2,
3: 3,
4: 4,
5: 5,
length: 6
}
我们成功了!
*/
从数组得到一个字符串 所有对象都具有toString方法和valueOf方法,数组也不例外:
var arr = [0 ,1 ,2 ,3 ,4 ];
console .log(arr.toString() );
console .log(arr.toString.join(',' ));
模拟栈和队列 学过数据结构的都知道这俩货是啥吧? 前者是先进后出,后者是先进先出;
对于栈,先进后出也就是后进先出,相当于我们总是在向一个管道里推入东西,而每次我们也只能从内容物的顶部取出东西。
在数组里模拟推入 的方法叫做push
,它可以接受任意数量
的参数,并把他们逐个添加到数组尾部,并且返回推入完毕后的数组长度 。
模拟从内容物的顶部取出东西的方法叫做shift
,它移除数组的第一项并返回它。
var arr2 = [0 ,1 ];
console .log( arr2.push(2 ) );
console .log( arr2.pop() );
对于队列,想象有一个管道,我们往里面塞入球体,那么最先进去的球一定是第一个从管道尾部被拿出来的。
这个放入球的过程在数组里叫做unshift
,它跟push一项可以接受任意数量个参数,并且将它们插入到数组的头部,返回数组的length
。
pop则是用来模拟从管道尾部拿球的方法,从数组末尾移除最后一项 (注意这次不是任意数量了,而且也不接收参数),而且返回被弹出的最后一项。
var arr3 = [2 ,3 ,4 ,5 ];
console .log( arr3.unshift(0 ,1 ) );
console .log( arr3.shift() );
数组有点乱,排个序吧? 第一个是让所有元素逆序的方法:reverse
,还有可以对数组按某种规则排序的sort
方法。
var arr4 = [6 ,5 ,4 ,3 ,2 ,1 ];
arr4.reverse();
console .log(arr4);
var arr5 = [2 ,6 ,3 ,5 ,6 ,8 ,9 ,1 ];
arr5.sort((a,b )=> a-b);
console .log(arr5);
复制一段当新数组之slice 它能够基于当前数组中的一个或者多个创建(浅复制)一个新数组。slice方法接收一个或两个参数,起始项和结束位置,记住,不包括结束位置的元素。如果没有最后一个参数,则默认结束位置为数组的length.这个方法返回起始位置到结束位置之间的项。
var arr6 = [ 0 ,1 ,2 ,3 ,{'key' :'value' }];
var arr7 = arr6.slice(4 )
console .log(arr7);
[[object Object] {
key: "value"
}]
*/
var arr8 = arr6.slice(0 ,4 );
console .log ( arr6[4 ] === arr7[0 ] );
强大的splice 它有三种作用: 删除,插入,替换。
可以删除任意数量的项,第一个参数是要删除的第一项的位置,第二个参数要删除的数量,这个方法始终返回被删除的项目组成的数组.
var arr9 = [1 ,2 ,3 ,4 ,5 ,6 ];
console .log( arr9.splice(0 ,3 ) );
console .log( arr9 );
可以向任意位置插入任意数量的项目,提供三个参数,起始位置,0(不删除),和要插入的项目
var arr10 = ['学挖掘机' ,'哪' ,'家' , '强?' ] ;
console .log(arr10.join('' )); "学挖掘机哪家强? 出门右转找蓝翔!"
可以向指定位置插入任意数量的项,同时删除任意数量的项,参数: 起始位置,删除的项目,插入的项目
var arr11 = ['php' ,'是坠吼的语言!' ];
arr11.splice(0 ,1 ,'JavaSctipt' ,'才' );
console .log(arr11.join('' ));
你在找人吗? indexOf
,lastIndexOf
,英语学的怎么样? 不用解释了把,上代码。
var arr12 = ['a' ,'a' ,'b' ,'c' ,'d' ];
console .log( arr12.indexOf('a' ) );
console .log( arr12.lastIndexOf('a' ) );
给我一个个搜-迭代 every
给定一个检查函数,如果数组每一项都使得这个函数返回true,则返回true. 对应的还有some
,只要检查函数有一个返回true,就返回true.
var arr13 = [0,1,2,3,4,5];
console.log( arr13.every(ele => ele <= 10) ); //true
console.log( arr13.some(ele => ele>=5) ); //true
filter
这次是用返回true的元素组成一个新 数组,记住,是新数组!
var arr14 = [10 ,11 ,12 ,0 ,1 ,2 ];
var arr15 = arr14.filter(function (ele ) {
return ele>=10 ;
});
console .log(arr15);
forEach
每一项都做点什么,不返回值.传入的函数具有三个参数,当前项,索引,数组本身。
var arr16 = ['你' ,'我' ,'' ];
arr16.forEach(function (ele,idx,arr ) {
if (ele === '' ){
arr[idx]+='不猜!?' ;
}else {
arr[idx]+='猜' ;
}
});
console .log(arr16.join('' ));
map
,这个函数跟forEach很像,但是它用每次调用函数的返回值形成一个新数组.使用上面的例子来看看
var arr16 = ['你' ,'我' ,'' ];
var arr17 = arr16.map(function (ele,idx,arr ) {
if (ele === '' ){
return ele+='猜不猜!?' ;
}else {
return ele+='猜' ;
}
});
console .log(arr17.join('' ));
reduce大法好 这也是一个很强大的方法,传入一个函数,接收4个参数:前一个值,当前值,项的索引,和数组对象. 除了函数外,还有一个可选的初始值参数。最后返回一个最终返回值。
var arr18 = [1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ]
var result = arr18.reduce((a,b )=> a+b);
console .log(result);
我们可以实现常见的Array Flatten
var arr = [1 ,[2 ,[3 ,4 ]],[5 ,6 ,[7 ,8 ]]];
var flatten = array => array.reduce( (acc,val ) => acc.concat(Array .isArray(val)? flatten(val) : val), []);
console .log( flatten(arr) );
我们还可以用它来做点高大上的事(高阶函数应用里reduce相当强大)
var __reduce__ = fn => (...args) => args.reduce((a, b ) => fn(a, b));
var add = (a,b )=> a+b;
var __add__ = __reduce__(add);
console .log( __add__(1 ,2 ,3 ,4 ,5 ,6 ,7 ,8 ,9 ) );
还有请注意一点: If initialValue isn't provided, reduce will execute the callback function starting at index 1, skipping the first index. If initialValue is provided, it will start at index 0.
*/
以上方法除了回调函数参数之外,还可以传入一个参数作为this的绑定
本质是对象 为什么要单独列出这一条?看如下代码:
var aFn = [];
var f1 = function (fn ) {
console .log(this .length);
console .log(this );
arguments [0 ]();
}
var f2 = function ( ) {
console .log(this .length);
}
aFn.push(f1,1 ,2 );
aFn[0 ](f2);
答案: 先输出3,再输出数组本身, 再输出1.
输出3 & 输出数组本身: this指向了数组本身,因为数组是一个对象啊!它充当了f1这个函数的调用者,所以函数内部的this指向了数组本身.
输出1: wait~!?哪来的1? 当然是arguments的length啊!!
这里又是一个trick,arguments是一个数组对象,是形参的一个映射。
arguments[0]存储着参数,而第一项则是f2,f2的this则指向了它的调用者:arguments对象
刚好arguments对象是具有length的. so....!! 是不是很阴险?
*/
String string.charAt(pos) 返回只含一个字母的字符串
string.indexOf(searchString, position) 返回字符串里面的字母所在的位置下标,实际上把把 string 看成一个 char[],更容易理解,postion代表从哪个位置开始查找,对应有一个lastIndexOf,从设定位置之前向前搜索。
string.slice(start, end) 返回子字符串,参数可以为负数
string.match(regexp) 返回比配字符串,假如有正则表达式为/xxx/g则,返回一个数组,否则返回第一次匹配到的字符串
string.replace(searchValue, replaceValue) 替换字符串,searchValue 可以为正则表达式。
str.substring(indexStart[, indexEnd]) 返回字符串的一部分,开始位置和停止位置,不包括停止位置,如果不传入第二个参数,就将字符串的长度作为结束位置 .
str.substr(start [, length]) 英语好的应该看出差别了吧,第二个参数是项数,不设这个参数同样将字符串长度作为结束位置 .