JavaScript笔记:数组

数组

      • 定义
    • 数组常用方法
      • a. 改变原数组(7种)
        • 1. push(item)
        • 2. pop()
        • 3. unshift(item)
        • 4. shift()
        • 5. reverse()
        • 6. splice(index, n, i1,......ix)
        • 7. sort( )
      • b. 不改变原数组
        • 1. concat()
        • 2. slice(start, end)
        • 3. join(separator)
        • 4. split(separator,n)
    • 类数组
    • 数组去重
    • forEach()
    • filter()
    • map()
    • every()
    • some()
    • reduce()
  • 数组类型的检测

ES3.0

定义

js中的数组是弱类型数组,不可以溢出读,但可以溢出写

var arr = [1, 2, 3];//数组字面量
var arr = new Array(1, 2, 3);//Array(5)若只有一个数值,则表示数组长度
var arr1 = [1,2]
console.log(arr1[3]); // undefined
arr1 [5] = 5;
console.log(arr1);  // 1,2,,,,5 

数组常用方法

a. 改变原数组(7种)

1. push(item)

从数组末尾开始添加,并返回数组新长度

var arr = [1, 2, 3];
//native code
Array.prototype.push = function(){
	for(var i = 0; i < arguments.length; i++){
		this[this.length] = arguments[i];
	}
	return this.length;
}

2. pop()

删除数组的最后一个元素并返回删除的元素。

var arr = [1,2,3];
var a = arr.pop();//a = 3

3. unshift(item)

向数组的开头添加一个或更多元素,并返回新的长度。

4. shift()

删除并返回数组的第一个元素。

5. reverse()

反转数组的元素位置

6. splice(index, n, i1,…ix)

返回截取的数组元素
index:必需,从何处开始添加或者删除元素,必须为数字,数组元素下标
n: 必需, 规定应该删除多少元素, 必须是数字,可为 “0”,如果未规定此参数,则删除从 index 开始到原数组结尾的所有元素。

var arr = [1,2,3,4,5,6];
var s = arr.splice(2,1);//s=[3], arr=[1,2,4,5,6]
arr.splice(2, 0, 3);//arr=[1,2,3,4,5,6]
arr.spilce(-1,0,7);//arr=[1,2,3,4,5,7,6]

7. sort( )

可选参数,但必须为函数,默认排序顺序为按字母升序。注意,当数字是按字母顺序排列时"40"将排在"5"前面,因为看“40”中的首位数’4.

//数字数组
var arr1 = [5,9,-8,16,0,2,7];
arr1.sort(function(a, b){
	return a-b;//升序
	// return b-a;降序
})
//字符串数组,不区分字母大小写排序
var arr2 = ['abc', 'haha', 'IT', 'ABC', 'hello'];
arr2.sort(function(s1, s2){
	var a = s1.toLowerCase();
	var b = s2.toLowerCase();
	if(a > b){
		return 1;
	}else{
		return -1;
	}
})
//对象数组,根据对象中某个属性值进行排序
var arr3 = [{name:'a',age:18},{name:'b',age:9},{name:'c',age:10}];
arr3.sort(function(a,b){
	return a.age - b.age;
})
//function objArrSort(keyName){
//	return function(objA, objB){
//		var a = objA[keyName],
//		    b = objB[keyName];
//		if(a > b){
//			return 1;
//		}else{
//			return -1;
//		}
//	}
//}
arr3.sort(objArrSort('age'));
		

** 给有序数组乱序**

//给有序的数组乱序
var arr = [1,2,3,4,5,6];
arr.sort(function(){
	return Math.random()-0.5;//Math.random()随机产生(0,1)开区间的数
})

字符串数组,按照字节长度排序

var arr = ['abkha','jhdifygfcdu','哈哈哈','wniacni'];
arr.sort(function(a,b){
	return retBytes(a) - retBytes(b);
})
function retBytes(str){
	var num = str.length;
	for(var i = 0; i < str.length; i++){
		if(str.charCodeAt(i) > 255){
			num++;
		}
	}
	return num;
}

b. 不改变原数组

1. concat()

用于连接两个或多个数组,不会改变原数组,只会返回一个被连接数组的一个副本

var a = [1,2,3],
    b = ['haha','hello'],
    c = a.concat(4,5,b,{name:'mike',age:18});
document.write(c);

2. slice(start, end)

start: 可选,规定从何处开始选取
end: 可选,规定从何处结束

3. join(separator)

用于把数组的所有元素转换成字符串,元素用指定的分隔符分割,返回值类型为String。
separator: 可选,指定要使用的分隔符。如果省略该参数,则使用逗号作为分隔符。

4. split(separator,n)

用于将字符串转换为字符串数组, 返回值类型为数组
separator:可选,字符串或正则表达式,从该参数指定的地方分割 string Object。
n : 可选。该参数可指定返回的数组的最大长度。如果设置了该参数,返回的子串不会多于这个参数指定的数组。如果没有设置该参数,整个字符串都会被分割,不考虑它的长度。

var arr = [1,2,3,'haha'];
var b = arr.join('~');
document.write(b);//1~2~3~haha
var c = b.split('~')
document.write(c);//["1","2","3","haha"]

类数组

  • 属性为索引(数字)属性
  • 必须有length属性
  • 最好加上push
var obj ={
"0": 'a',
"1": 'b',
"2": 'c',
"length": 3,
"push": Array.prototype.push
}
var obj1 = {
    "2": 'a',
    "3": 'b',
    "length": 2,
    "push": Array.prototype.push
}
obj1.push("c");
obj1.push("d");
//obj1={
//	"2": 'c', 因为obj1[obj1.length]="c",obj1.length++
//      "3": 'd', obj1[obj1.length]="d",
//      "length": 4,
//      "push":.....
//Array.prototype.push = function(target){
//this[this.length] = arguments;
//this.length++;
}

数组去重

Array.prototype.unique = function(){
	//1. hash 新数组,新对象
	var temp = {},
		arr = [],
		len = this.length
	for(var i = 0; i < len; i++){
		if(!temp[this[i]]){
			temp[this[i]] = "haha";
			arr.push(this[i]);
		}
	}
	//2. forEach + indexOf + 新数组
	this.forEach((item, index, array) => {
        if(array.indexOf(item) === index) {
            arr.push(item);
        }
    });
	return arr;
	//3. filter + indexOf
	//return this.filter((item, index, array) =>  array.indexOf(item) === index);
}

返回一个字符串中首次出现的字符

var str = 'jaifbainajkbaaurhfrurwoiidhcwababsjhwijwopt';
function ret(str){
	var temp = {},
		reArr = [],//reArr = '';
		arr = str.split(''),
		len = arr.length;
	for(var i = 0; i < len; i++){
		if(!temp[arr[i]]){
			temp[arr[i]] = 'haha';
			reArr.push(arr[i]);// reArr += arr[i];
		}
	}
	return reArr;
}		
var a = ret(str);		document.write(a);//j,a,i,f,b,n,k,u,r,h,w,o,d,c,s,p,t||jaifbnkurhwodcspt

ECMA Script5中数组方法如indexOf()、forEach()、map()、filter()、some()并不兼容IE6~8

forEach()

forEach(function(elem, index, self), )
用于调用数组的每个元素,并将元素传递给回调函数。

var liArray = document.getElementsByTagName('li');
var arr = [
	{name:'aaa'},
	{name:'bbb'},
	{name:'ccc'}
];
//源码
Array.prototype.myForEach = function(func){
	var len = this.length;
	for(var i = 0; i < len; i++){
		func(this[i], i, this);
	}
}
function deal(elem, index, self){
	liArray[index].innerText = elem.name;
}
arr.myForEach(deal);

filter()

创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
不会对空数组进行检测,也不会改变原始数组。

var arr = [
	{name:'aaa'},
	{name:'bbb'},
	{name:'ccc'}
];
Array.prototype.myFilter = function(func){
	var len = this.length;
	var newArr = [];
	var _this = arguments[1] || window;
	for(var i = 0; i < len; i++){
		func.apply(_this, [this[i], i, this]) && newArr.push(this[i]);
	}
	return newArr;
}
var newArray = arr.myFilter(function(elem, index, self){
	return elem.name == 'ccc';
});
console.log(newArray); //[{name: "ccc", age: 20}]

map()

返回一个新数组,数组中的元素为原始数组元素调用函数处理后的值。
不会对空数组进行检测,也不会改变原始数组。

var arr = [
	{name:'aaa', age: 20},
	{name:'bbb', age: 20},
	{name:'ccc', age: 20}
];
Array.prototype.myMap = function(func){
	var len = this.length;
	var newArr = [];
	var _this = arguments[1] || window;
	for(var i = 0; i < len; i++){
		newArr.push(func.call(_this, this[i], i, this));
	}
	return newArr;
}
var newArray = arr.myMap(function(elem, index, self){
	return elem.name;
});
console.log(newArray); //["aaa", "bbb", "ccc"]

every()

用于检测数组所有元素是否都符合指定条件(通过函数提供)。
不会对空数组进行检测,也不会改变原始数组。

  • 如果数组中检测到有一个元素不满足,则整个表达式返回 false ,且剩余的元素不会再进行检测。
  • 如果所有元素都满足条件,则返回 true。
Array.prototype.myEvery = function(func){
	var len = this.length;
	var flag = true;
	var _this = arguments[1] || window;
	for(var i = 0; i < len; i++){
		if(func.apply(_this,[this[i], i, this]) == false){
			flag = false;
			break;
		}
	}
	return flag;
}

some()

用于检测数组元素是否都符合指定条件(通过函数提供)。
不会对空数组进行检测,也不会改变原始数组。

  • 如果数组中检测到有一个元素满足,则返回 true ,且剩余的元素不会再进行检测。
  • 如果所有元素都不满足条件,则返回 false。

reduce()

reduce(function(total, currentValue, currentIndex, arr), initialValue)

var str = "BAIDUID=D6C3177BBC286DEB9CC0D638F3D6D540:FG=1; BIDUPSID=D6C3177BBC286DEB9CC0D638F3D6D540; PSTM=1543559736; BD_UPN=12314753; BDORZ=FFFB88E999055A3F8A630C64834BD6D0; __guid=136081015.4125913337596453000.1543936031300.835; BDRCVFR[n9rYh9b3bT0]=mk3SLVN4HKm; delPer=0; BD_HOME=0; H_PS_PSSID=; BD_CK_SAM=1; PSINO=7; monitor_count=10"
function parseStr(str){
	var obj = {};
	var arr = str.split(';');
	arr.myReduce(function(init, curr, index, self){
		var currArr = curr.split('=');
		init[currArr[0]] = currArr[1];
		return init
	}, obj)
	return obj;
}
Array.prototype.myReduce = function(func, initialValue){
	var len = this.length,
		retValue = initialValue,
		_this = arguments[2] || window;
	for(var i = 0; i < len; i++){
		retValue = func.apply(_this, [retValue, this[i], i, this]);
	}
	return retValue;
}
console.log(parseStr(str));

数组类型的检测

在ES5中,有一个isArray()方法来检测是否是数组,但在ES5之前要检测是否是数据类型很麻烦

  • typeof运算符,数组和对象都会返回object,无法分清数组和对象
  • constructor和instanceof操作符是目前为止最好用的,但都存在潜在问题

web浏览器中可能有多个窗口或窗体,每一个窗体有自己的js环境,有自己的全局对象,并且每个全局对象有自己的构造函数,
因此一个窗体中的对象将不可能是另外窗体中的构造函数的实例,窗体之间的混淆不常发生,但这个问题已经证明了constructor和instanceof都不能真正可靠的检测数组类型

  • Object.prototype.toString.call(arr) ===’[object Array]’
    这是最可靠的检测是否是数组类型的方法

你可能感兴趣的:(前段)