js正确地使用fill()初始化二维数组:
fill()方法都知道,填充/改变 数组
比如:
let a = new Array(5).fill(0);
console.log(a); // 输出结果为[0, 0, 0, 0, 0]
当我们想使用fill创建一个二维数组时
let arr=new Array(5).fill(new Array(5).fill(0))
console.log(arr)
原因
fill()的参数不是基本类型时,比如数组、对象,并不是将它的值填充到数组,而是将它的地址填充到数组,所以填充后数组的每一项都指向的是同一个地址,就会出现"牵一发而动全身"的现象。
解决方法:使用map()给每个第一维的数组分别赋值
let arr4=new Array(5).fill(0).map(item=>new Array(5)) //二维的用不用fill填充都行,但是一维的必须填充,如果一维不填充,会导致比如 arr4[1][0]=8 就会报错,因为内存中压根就没开辟这个空间
//原因就是如果一维都不用fill填充,那么二维还怎么依赖他创建
let arr4=new Array(5).fill(0).map(item=>new Array(5).fill(0))
arr[1][1]=1
console.log(arr) //这样就只有arr[1][1]发生改变了,完美解决。
创建一维数组的两种方式:
1、利用数组字面量
var arr = [1, 2, 3];
console.log(arr); //输出结果为1,2,3
2、利用new Array()
var arr1 = new Array(); //创建了一个空的数组
console.log(arr1); //[]
var arr2 = new Array(2); //里面的2表示数组的长度为2,输出结果我2个空的数组元素
//虽然规定了长度,但要想任意再加长度之外的数组成员也是可以的 ,不受长度限制
console.log(arr2); // [empty × 2]
var arr3 = new Array(2, 3); //等价于[2,3]
console.log(arr2); // [2, 3]
es6新增的三个api:
Set:set类似于数组,成员是唯一的
(1)成员不能重复
(2)只有键值没有键名,类似数组
(3)可以遍历,方法有add, delete,has
1.new Set()-----创建set对象
2.set.add(value)----存储值
3.set.get(value)---- set中不存在直接得到某个值的方法,若想取某个值必须用for of遍历,for或者forin都不行
4.set.has(value)----如果值存在则返回true,负责返回false
5.set.delete(value)----删除指定值
6.set.clear()----清空set
7.set.size----返回当前元素个数
Map:map类似于对象
(1)本质上是健值对的集合,类似集合
(2)可以遍历,可以跟各种数据格式转换
1.new Map()-----创建map对象
2.map.set(key,value)----根据键存储值
3.map.get(key)----根据键来返回值,如果map中不存在对应的key,则返回undefined
4.map.has(key)----如果key存在则返回true,负责返回false
5.map.delete(key)----删除指定键的值
6.map.clear()----清空map
7.map.size----返回当前元素个数
map和set构造函数具体可参考这篇文章
Set是es6新增的数据结构,类似于数组也类似对象,但它的一大特性就是所有元素都是唯一的,没有重复的值,我们一般称为集合。
Set是一个构造函数,用来生成 Set 数据结构(构造函数中有对数组特有的 添加元素add方法、删除元素 delete方法、判断某元素是否存在has方法、清除所有元素clear方法 )
Array.from() 方法可将拥有 length 属性的对象或可迭代的对象(迭代就是可根据上一次值推出下一次值,比如for循环语句)转化为一个数组并返回(es6新增)
new Set()和Array.from() 结合用来数组去重
new Set(),用来数组去重。
Set类似于数组,区别在于它所有的成员都是唯一的,不能有重复的值
Array.from()或者...扩展运算符可以将set数据结构变更为数组形式
数值去重:
let arr = [1, 2, 2, 3]; // [1, 2, 2, 3]
let set = new Set(arr); //去掉重复数据,返回结果是'set'
let newArr = Array.from(set); //将set转化为数组或者利用扩展运算符
let newArr2=[...set] //通过...扩展运算符将set变更为数组形式
console.log(newArr2); // [1, 2, 3]
console.log(newArr); // [1, 2, 3]
对象用变量表示去重:
const b={a:2}
let arr = [{a:1}, b, b, {a:3}]; //[{a:1},{a:2},{a:2},{a:3}]
let set = new Set(arr);
let newArr = Array.from(set);
console.log(newArr); // [{a:1},{a:2},{a:3}]
无法直接对象去重:
let arr = [{a:1}, {a:2}, {a:2}, {a:3}]; //[{a:1},{a:2},{a:2},{a:3}]
let set = new Set(arr);
let newArr = Array.from(set);
console.log(newArr); //[{a:1},{a:2},{a:2},{a:3}]
/// 将Set结构的数据转换为真正的数组
let arr = [12,45,97,9797,564,134,45642]
let arr2 = new Set(arr) //arr2是可迭代的对象,但没有 length 属性,有size属性
console.log(Array.from(arr2)) // [ 12, 45, 97, 9797, 564, 134, 45642 ]
var myarr=Array.from("sdv") //sdv是可迭代的对象
console.log(myarr); //['s', 'd', 'v']
let arrayLike = {
0: 'tom',
1: '65',
2: '男',
3: ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike)
console.log(arr) // ['tom','65','男',['jane','john','Mary']]
let arrayLike = {
'name': 'tom',
'age': '65',
'sex': '男',
'friends': ['jane','john','Mary'],
'length': 4
}
let arr = Array.from(arrayLike) //arrayLike的键导致arrayLike是不可迭代的对象
console.log(arr) // [ undefined, undefined, undefined, undefined ]
Javascript五种方法获取数组中最小值:
var arry = [1, 3, 2, 9, 5, 3, 1, 5, 3, 0, 9, 3, 2, 4, 2, 5, 7];
//方法一:循环遍历
var minNum = arry[0];
arry.forEach((val, index) => {
if (val < arry[index + 1] && val < minNum) {
minNum = val;
}
})
console.log(minNum)
//方法二:sort()
sort() 方法用于对数组的元素进行排序。排序顺序可以是字母或数字,并按升序或降序。
默认排序顺序为根据ASCLL码升序。当数字是按字母顺序排列时"40"将排在"5"前面(因为是根据ASCLL码进行排序)。
所以你必须通过一个函数作为参数来调用。函数指定数字是按照升序还是降序排列。
sort()可以接收一个携带两个形参的callback(a,b),即a、b是两个即将要比较大小的元素,且必须要有返回值。
当callback的返回值是正数时、那么 b 会被排列到 a 之前;
当callback的返回值是负数时、那么 a 会被排列到 b 之前;
当callback的返回值是为 0 时、那么 a 与 b 的位置保持不变;
sort每执行一次会根据返回值调换两个参数a、b在原数组中的位置
(a = > 当前项、b当前项的下一项)
arry.sort((a,b) => {
return a-b
})
console.log(arry[0])
//方法三:Math.min()+...
Math.min(...arry)
//方法四:reduce()
let arry = [11, 12, 13, 14, 15, 16, 17, 12, 12, 9, 11];
let result = arry.reduce((x, y) => x < y ? x : y)
console.log(result)//9
//方法五:巧用apply方法,因为apply方法它在执行的时候,可以将传入的数组解析成一个一个的元素。
let arr = [23,1,33,6,8,2];
min = Math.min.apply(null,arr)
console.log(min) //1
JS中对象的四种遍历方法:
- for in 遍历
for in用来遍历对象自身和其可枚举属性(不含symbol属性),且可遍历对象原型上的属性。
let obj = {
name: 'hong',
age: 20,
sex: 'nan'
}
Object.prototype.scholl = 'wyu'
Object.prototype.say = function () {
console.log('hello!')
}
for (let i in obj) {
console.log(i + ':' + obj[i])
}
// 打印以下信息
// name:hong
// age:20
// sex:nan
// scholl:wyu
// say:function () {
// console.log('hello!')
// }
若只遍历对象上的实例属性,不遍历对象原型上的属性,可用 hasOwnProperty 来判断一下是否为该对象实例的属性,再进行遍历。
for (let i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i + ':' + obj[i])
}
}
// 输出
name:hong
age:20
sex:nan
- 使用 Object.keys (返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性))和 Object.values 遍历
let obj = {
name: 'hong',
age: 20,
sex: 'nan'
}
console.log(Object.keys(obj)) //[ 'name', 'age', 'sex' ]
console.log(Object.values(obj)) //[ 'hong', 20, 'nan' ]
Object.keys在内部会根据属性名key的类型进行不同的排序逻辑,分三种情况:
如果属性名的类型是Number,那么Object.keys返回值是按照key从小到大排序
如果属性名的类型是String,那么Object.keys返回值是按照属性被创建的时间升序排序。
如果属性名的类型是Symbol,那么逻辑同String相同
- Object.getOwnPropertyNames(obj) 方法
返回一个数组,包含对象自身的所有属性(不含Symbol属性,但是包括不可枚举属性).
let obj = {
name: 'hong',
age: 20,
sex: 'nan'
}
let objKeys = Object.getOwnPropertyNames(obj)
console.log(objKeys) //[ 'name', 'age', 'sex' ]
4.Reflect.ownKeys(obj)遍历
返回一个数组,包含对象自身的所有属性,不管属性名是Symbol或字符串,也不管是否可枚举
let obj = {
name: 'hong',
age: 20,
sex: 'nan'
}
console.log(Reflect.ownKeys(obj)) //['name', 'age', 'sex']
Reflect是ES6提供的新对象,将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty,Proxy对象上所有新增函数等),放到Reflect对象上,从Reflect上能拿到js语言内部的方法。
Reflect也算是一个js内置对象,它提供拦截JavaScript操作的方法。Reflect不是一个函数对象,因此它是不可构造的。
说一个Reflect对象方法和object对象方法的不同:
Reflect.defineProperty()是一个静态的方法,看起来像Object.defineProperty()但是它返回一个布尔值
Object.defineProperty()也是静态方法,但返回更改后的对象
const object1 = {};
console.log(Reflect.defineProperty(object1, "property1", { value: 42 })); //true
console.log(Object.defineProperty(object1, "property2", { value: 30 })); //{property1: 42, property2: 30}
console.log(object1); //{property1: 42, property2: 30}
静态方法对应实例(动态)方法:
静态方法
function A(){}
A.sayMeS=function(){
console.log("Hello World S!");
}
A.sayMeS();//输出Hello World S!
(动态)实例方法
function A(){
this.sayMeE=function(){
console.log("Hello World E!");
}}
A.sayMeE() //A.sayMeE is not a function 报错
var a=new A(); //var a是A的一个引用,也就是指针,a就可以指向sayMeE这个方法
a.sayMeE();//输出Hello World E!
附(不知名知识点):
for…in循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性
Object.assign():只拷贝对象自身的可枚举的属性。
其中,只有for…in会返回继承的属性,其他三个方法都会忽略继承的属性,只处理对象自身的属性
实际上,引入“可枚举”(enumerable)这个概念的最初目的,就是让某些属性可以规避掉for…in操作,
不然所有内部属性和方法都会被遍历到。比如,对象原型的toString方法,以及数组的length属性,
就通过“可枚举性”,从而避免被for…in遍历到。