首先可以给js的数组对象定义一个函数,用于查找指定的元素在数组中的位置,即索引,代码为:
Array.prototype.indexOf = function(val) {
for (var i = 0; i < this.length; i++) {
if (this[i] == val) return i;
}
return -1;
};
然后使用通过得到这个元素的索引,使用js数组自己固有的函数去删除这个元素
Array.prototype.remove = function(val) {
var index = this.indexOf(val);
if (index > -1) {
this.splice(index, 1);
}
};
var emp = ['abs','dsf','sdf','fd']
假如我们要删除其中的 'fd' ,就可以使用:
emp.remove('fd');
删除的数组的某一项
splice(index,len,[item]) 注释:该方法会改变原始数组。
splice有3个参数,它也可以用来替换/删除/添加数组内某一个或者几个值
index:数组开始下标 len: 替换/删除的长度 item:替换的值,删除操作的话 item为空
如:arr = ['a','b','c','d']
//删除起始下标为1,长度为1的一个值(len设置1,如果为0,则数组不变)
var arr = ['a','b','c','d'];
arr.splice(1,1);
console.log(arr);
//['a','c','d'];
//删除起始下标为1,长度为2的一个值(len设置2)
var arr2 = ['a','b','c','d']
arr2.splice(1,2);
console.log(arr2);
//['a','d']
//替换起始下标为1,长度为1的一个值为‘ttt’,len设置的1
var arr = ['a','b','c','d'];
arr.splice(1,1,'ttt');
console.log(arr);
//['a','ttt','c','d']
var arr2 = ['a','b','c','d'];
arr2.splice(1,2,'ttt');
console.log(arr2);
//['a','ttt','d'] 替换起始下标为1,长度为2的两个值为‘ttt’,len设置的1
添加 ---- len设置为0,item为添加的值
var arr = ['a','b','c','d'];
arr.splice(1,0,'ttt');
console.log(arr);
//['a','ttt','b','c','d'] 表示在下标为1处添加一项'ttt'
delete删除掉数组中的元素后,会把该下标出的值置为undefined,数组的长度不会变
var arr = ['a','b','c','d'];
delete arr[1];
arr;
//["a", undefined × 1, "c", "d"] 中间出现两个逗号,数组长度不变,有一项为undefined
// Array Remove - By John Resig (MIT Licensed)
Array.prototype.remove = function(from, to) {
var rest = this.slice((to || from) + 1 || this.length);
this.length = from < 0 ? this.length + from : from;
return this.push.apply(this, rest);
};
// 移除数组中的第二项
array.remove(1);
// 移除数组中的倒数第二项
array.remove(-2);
// 移除数组中的第二项和第三项(从第二项开始,删除2个元素)
array.remove(1,2);
// 移除数组中的最后一项和倒数第二项(数组中的最后两项)
array.remove(-2,-1);
pop() 删除掉数组的最后一个元素
let myFish = ["angel", "clown", "mandarin", "surgeon"];
let popped = myFish.pop();
console.log(myFish);
// ["angel", "clown", "mandarin"]
console.log(popped);
// surgeon
JavaScript删除数组第一个元素的几种方法(不改变原数组,返回新数组)
1、slice() 浅克隆去复制 arr 元素从第二个开始到最后一个
var arr = [1, 2, 3, 4, 5];
var newArr = arr.slice(1);
console.log(newArr);
2、splice()的删除功能
var arr = [1, 2, 3, 4, 5];
var newArr = arr.slice(0);
newArr.splice(0, 1);
console.log(newArr);
3、filter() 过滤下标,返回满足不等0的下标的元素
var arr = [1, 2, 3, 4, 5];
var newArr = arr.filter((val, index, arr) => {
return index !== 0;
})
console.log(newArr);
4、shift() 删除数组的首个元素
var arr = [1, 2, 3, 4, 5];
var newArr = arr.slice(0);
newArr.shift();
console.log(newArr);
5、join() 字符串连接后,用split()进行分离为新数组
var arr = [1, 2, 3, 4, 5];
var newArr = arr.join().split(',').map(Number); // arr.map(Number):字符串元素转为数字元素
newArr.shift();
console.log(newArr);
6、apply() 数组参数化后放入[]数组
var arr = [1, 2, 3, 4, 5];
var newArr = [];
[].push.apply(newArr, arr);
newArr.shift();
console.log(newArr);
7、concat() 数组链接出新数组
var arr = [1, 2, 3, 4, 5];
var newArr = arr.concat();
newArr.shift();
console.log(newArr);
[JS数组添加元素的三种方式]
1、push() 结尾添加
2、unshift() 头部添加
3、splice() 方法向/从数组指定位置添加/删除项目,然后返回被删除的项目。
js 数组过滤空值(undefined、null、""、0、false、NaN)
const arr = [undefined, null, "", 0, false, NaN, 1, 2].filter(Boolean);
// arr => [1, 2]
var arr = ['A', '', 'B', null, undefined, 'C', ' '];
var r = arr.filter(function (s) {
return s&& s.trim();
});
console.log(r) // ["A", "B", "C"]
1.filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。
注意: filter() 不会对空数组进行检测。
注意: filter() 不会改变原始数组。
2 .js的判断条件中,0,‘’,undefined , null,NaN都视为false
所以,当 s&& s.trim() 为false时,当前数组的元素会被过滤掉。
3.trim() 方法用于删除字符串的头尾空格。
trim() 方法不会改变原始字符串。
IE9以下不支持trim()方法,需要使用正则表达式来实现:
function myTrim(x) {
return x.replace(/^\s+|\s+$/gm,'');
}
function myFunction() {
var str = myTrim(" Hello ");
alert(str); //Hello
}
array去重
引用:https://blog.csdn.net/weixin_42412046/article/details/81459294
Methods 1: 思路:定义一个新数组,并存放原数组的第一个元素,然后将元素组一一和新数组的元素对比,若不同则存放在新数组中。
function unique(arr) {
let newArr = [arr[0]];
for (let i = 1; i < arr.length; i++) {
let repeat = false;
for (let j = 0; j < newArr.length; j++) {
if (arr[i] === newArr[j]) {
repeat = true;
break;
}else{
}
}
if (!repeat) {
newArr.push(arr[i]);
}
}
return newArr;
}
console.log(unique([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 2: 思路:先将原数组排序,在与相邻的进行比较,如果不同则存入新数组。
function unique2(arr) {
var formArr = arr.sort()
var newArr=[formArr[0]]
for (let i = 1; i < formArr.length; i++) {
if (formArr[i]!==formArr[i-1]) {
newArr.push(formArr[i])
}
}
return newArr
}
console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 4,5, 6, 7]
Methods 3: 利用对象属性存在的特性,如果没有该属性则存入新数组。
function unique3(arr) {
var obj={}
var newArr=[]
for (let i = 0; i < arr.length; i++) {
if (!obj[arr[i]]) {
obj[arr[i]] = 1
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique2([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 4: 利用数组的indexOf下标属性来查询。
function unique4(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (newArr.indexOf(arr[i])===-1) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique4([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 5: 利用数组原型对象上的includes方法。
function unique5(arr) {
var newArr = []
for (var i = 0; i < arr.length; i++) {
if (!newArr.includes(arr[i])) {
newArr.push(arr[i])
}
}
return newArr
}
console.log(unique5([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 6: 利用数组原型对象上的 filter 和 includes方法。
function unique6(arr) {
var newArr = []
newArr = arr.filter(function (item) {
return newArr.includes(item) ? '' : newArr.push(item)
})
return newArr
}
console.log(unique6([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 7: 利用数组原型对象上的 forEach 和 includes方法。
function unique7(arr) {
var newArr = []
array.forEach(item => {
return newArr.includes(item) ? '' : newArr.push(item)
});
return newArr
}
console.log(unique7([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 8: 利用数组原型对象上的 splice 方法。
function unique8(arr) {
var i,j,len = arr.length;
for (i = 0; i < len; i++) {
for (j = i + 1; j < len; j++) {
if (arr[i] == arr[j]) {
arr.splice(j, 1);
len--;
j--;
}
}
}
return arr;
}
console.log(unique8([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
Methods 9: 利用数组原型对象上的 lastIndexOf 方法。
function unique9(arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
res.lastIndexOf(arr[i]) !== -1 ? '' : res.push(arr[i]);
}
return res;
}
console.log(unique9([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
Methods 10: 利用 ES6的set 方法。
function unique10(arr) {
//Set数据结构,它类似于数组,其成员的值都是唯一的
return Array.from(new Set(arr)); // 利用Array.from将Set结构转换成数组
}
console.log(unique10([1, 1, 2, 3, 5, 3, 1, 5, 6, 7, 4]));
// 结果是[1, 2, 3, 5, 6, 7, 4]
JS中的深拷贝和浅拷贝
相关知识点
1.javascript变量包含两种不同数据类型的值:基本类型和引用类型。
基本类型值指的是简单的数据段,包括es6里面新增的一共是有6种,具体如下:number、string、boolean、null、undefined、symbol。
引用类型值指那些可能由多个值构成的对象,只有一种如下:object。
在将一个值赋给变量时,解析器必须确定这个值是基本类型值还是引用类型值。
2.javascript的变量的存储方式:栈(stack)和堆(heap)。
栈:自动分配内存空间,系统自动释放,里面存放的是基本类型的值和引用类型的地址
堆:动态分配的内存,大小不定,也不会自动释放。里面存放引用类型的值。
image.png
基本数据类型是按值访问的,因为可以操作保存在变量中的实际的值。
引用类型的值是保存在内存中的对象。JavaScript 不允许直接访问内存中的位置,也就是说不能直接操作对象的内存空间。 在操作对象时, 实际上是在操作对象的引用而不是实际的对象。
基本类型与引用类型最大的区别实际就是 传值与传址 的区别
值传递:基本类型采用的是值传递。
地址传递:引用类型则是地址传递,将存放在栈内存中的地址赋值给接收的变量。
浅拷贝
浅拷贝
被复制对象的所有变量都含有与原来的对象相同的值,而所有的对其他对象的引用仍然指向原来的对象。即对象的浅拷贝会对“主”对象进行拷贝,但不会复制主对象里面的对象。”里面的对象“会在原来的对象和它的副本之间共享。
基本数据类型Number(赋值操作)
let a=1;
let b=a;
b //1
b=2;
b //2
a //1
数组
let arr1 = [1,2,3];
let arr2 = arr1;
arr2 //[1,2,3]
arr2.push(4);
arr2 //[1,2,3,4]
arr1 //[1,2,3,4]
image.png
首先栈内存arr1会指向堆内存里的数组,栈内存的arr1保存的是数组的引用,也就相当于内存地址,arr2=arr1,会把arr1的引用赋给arr2,所以arr2也有了数组的引用,此时arr1和arr2指向的是同一个数组,因此一个数组的改变会影响另一个数组的值。
对象
let obj1={count:1,name:'grace',age:1};
let obj2 = obj1;
obj2 //{count:1,name:'grace',age:1}
obj2.count=2;
obj1 //{count:2,name:'grace',age:1}
obj2 //{count:2,name:'grace',age:1}
综上所述,如果是基本数据类型,直接进行赋值操作,这样就相当于在栈内存中重新开辟了一个新的空间把值传递过去;如果是引用类型的值传递,进行的就是浅拷贝,浅拷贝赋值的只是对象的引用,如上述obj2=obj1,实际上传递的只是obj1的内存地址,所以obj2和obj1指向的是同一个内存地址,所以这个内存地址中值的改变对obj1和obj2都有影响。
深拷贝
深拷贝不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深复制的方法递归复制到新对象上,所以对一个对象的修改并不会影响另一个对象。
数组(注意:该数组只是单纯的数组,如果数组里面嵌套对象,则下面的几种方法都不是深拷贝。) --更新于 2020.02.26
法一:for循环
let arr1 = [1,2,3];
let arr2 = copyArr(arr1);
function copyArr(arr){
let res=[];
for(let i=0,length=arr.length;i<length;i++){
res.push(arr[i]);
}
return res;
}
法二: slice
利用数组自身的方法,slice、concat方法在运行后会返回新的数组
let arr1 = [1,2,3];
let arr2 = arr1.slice(0);
法三: concat
let arr1 = [1,2,3];
let arr2 = arr1.concat();
法四:扩展运算符
let arr1 = [1,2,3];
let [...arr2] = arr1;
法五:Array.from
如果参数是一个真正的数组,Array.from会返回一个一模一样的新数组
let arr1 = [1,2,3];
let arr2 = Array.from(arr1);
对象
法一:for循环
let obj1={count:1,name:'grace',age:1};
let obj2 = copyObj(obj){
let res = {};
for(let key in obj){
res[key]=obj[key];
}
return res;
}
法二:利用JSON
let obj1={count:1,name:'grace',age:1};
let obj2 = JSON.parse(JSON.stringify(obj1));
//使用JSON比较简单,但是JSON的深拷贝方式会忽略函数对象和原型对象(有待考证)
法三:扩展运算符
let obj1={count:1,name:'grace',age:1};
let {...obj2} = obj1;
合成版,可以实现数组和对象的深拷贝
function deepCopy(obj){
let result = Array.isArray(obj)?[]:{};
if(obj && typeof obj === 'object'){
for(let key in obj){
if(obj.hasOwnProperty(key)){
if(obj[key]&&typeof obj[key]==='object'){
result[key]=deepCopy(obj[key]);
}else{
result[key]=obj[key];
}
}
}
}
return result;
}
注意:ES6新增了Object.assign() 方法
第一个参数是目标对象,之后还可以跟一个或多个源对象。它会遍历一个或多个源对象可枚举的自有键并把它们复制到目标对象,最后返回目标对象
assign是使用=操作符来赋值,
Object.assign() 只是一级属性复制,比浅拷贝多深拷贝了一层而已。用的时候,还是要注意这个问题的
引用:https://blog.csdn.net/baidu_36065997/article/details/80309991
参考:https://www.jianshu.com/p/2aa380414a0e
数组合并
var arr1 = [1, 2, 3];var arr2 = ["a","b","c","d","e","f"];
1、concat
var arr = arr1.concat(arr2); // [1, 2, 3, "a", "b", "c", "d", "e", "f"]
//函数的apply方法有一个特性,那就是func.apply(obj,argv),argv是一个数组。所以我
//们可以利用这点,直接上代码:
1.
arr1.push.apply(arr1,arr2);
console.log(arr1) // [1, 2, 3, "a", "b", "c", "d", "e", "f"]
2.
Array.prototype.push.apply(arr1,arr2);
console.log(arr1) // [1, 2, 3, "a", "b", "c", "d", "e", "f"]
es6拓展运算
arr = [...arr1,...arr2]
console.log(arr) // [1, 2, 3, "a", "b", "c", "d", "e", "f"]
网友评论