- js
数组去重的方法
- 最常用的方式
function filter(args) {
var arr=[]
for(let i=0;i<args.length;i++){
if(arr.indexOf(args[i])==-1){
arr.push(args[i])
}
}
return arr
}
var arr1=[1,2,3,2,3,4,4,5]
console.log(filter(arr1)) // [1,2,3,4,5]
- 对象键值法去重
function uniq(args){
var temp={},r=[],val,type
for(let i=0;i<args.length;i++){
val=args[i] // 1,2,3,2,3,4
type=typeof val
console.log(temp[val]) // number
if(!temp[val]){
temp[val]=[type]
r.push(val)
}else if(temp[val].indexOf(type)<0){
temp[val].push(type)
r.push(val)
}
}
return r
}
var arr2=[1,2,3,2,3,4,4,5]
console.log(uniq(arr2)) // [1,2,3,4,5]
- es6 Set方法一键去重
var arr=[1,1,2,3,2,4,4,6]
arr=new Set(arr)
console.log([...arr]) // [1, 2, 3, 4, 6]
js常见的循环与遍历以及不同循环遍历之间的区别
- for 循环遍历
var arr=[1,1,2,3,2,4,4,6]
for(let i=0;i<arr.length;i++){
console.log(arr[i]);
}
// 1,1,2,3,2,4,4,6
// for循环 需要知道数组的长度
- forEach循环
// forEach循环,循环数组中每一个元素并采取操作, 没有返回值, 可以不用知道数组长度
var arr=["Andy",30,180,"male"]
arr.forEach((value,key)=>{
console.log(value) // Andy 30 180 male
console.log(key) // 0 1 2 3
})
// forEach循环不能循环遍历对象
console.log(Array.prototype.hasOwnProperty("forEach")) // true
console.log(Object.prototype.hasOwnProperty("forEach")) // false
// 可知, forEach方法时定义在 Array原型链上的。 所以对象不能 forEach
- map 循环
// map函数,遍历数组每个元素,并回调操作,需要返回值,返回值组成新的数组,原数组不变
var arr=[1,1,2,3,4,4,5]
arr.map((value,key)=>{
console.log(value) // 1 1 2 3 4 4 5
console.log(key) // 0 1 2 3 4 5 6
})
// map循环里面存在一个回调函数,所以可以实现改变数组内容,参照下面的代码,原数组不变。
var arr=[1,1,2,3,4,4,5]
var tt=arr.map((i)=>{
i=i+"world";
return i
})
console.log(tt) // ["1world", "1world", "2world", "3world", "4world", "4world", "5world"]
console.log(arr) // [1, 1, 2, 3, 4, 4, 5]
- filter函数
// filter函数, 过滤通过条件的元素组成一个新数组, 原数组不变
var arr=["J.R.Smith",30,"kidding","naive",33,12,0,null,undefined,1,8,7]
var tt=arr.filter(i=>{
return typeof i=="number"
})
console.log(arr); // ["J.R.Smith", 30, "kidding", "naive", 33, 12, 0, null, undefined, 1, 8, 7]
console.log(tt) // [30, 33, 12, 0, 1, 8, 7]
// filter方法提供了一个可以过滤数组的途径。
- some函数
// some函数,遍历数组中是否有符合条件的元素,返回Boolean值
var arr=["J.R.Smith",30,"kidding","naive",33,12,0,null,undefined,1,8,7]
var tt=arr.some(i=>{
return typeof i=="number"
})
console.log(arr); // ["J.R.Smith", 30, "kidding", "naive", 33, 12, 0, null, undefined, 1, 8, 7]
console.log(tt) // true
- every函数
// every函数, 遍历数组中是否每个元素都符合条件, 返回Boolean值
var arr=["J.R.Smith",30,"kidding","naive",33,12,0,null,undefined,1,8,7]
var tt=arr.every(i=>{
return typeof i=="number"
})
console.log(arr); // ["J.R.Smith", 30, "kidding", "naive", 33, 12, 0, null, undefined, 1, 8, 7]
console.log(tt) // false
-
for...in遍历
for...in
语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。
// `for...in` 循环只遍历可枚举属性。
var obj={
name:"Andy",
age:30,
weight:180,
sex:'male'
}
for(let i in obj){
console.log(i,obj[i]) // name Andy
// age 30
// weight 180
// sex male
}
下面代码展示了,当对象的enumerable属性被设置为false时候,不能被for...in 遍历
var obj={
name:"Andy",
age:30,
weight:180,
sex:'male'
}
Object.defineProperty(obj,"age",{
enumerable:false,
configurable:false,
writable:false,
value:"static"
})
for(let i in obj){
console.log(i,obj[i])
}
enumerable
上图可以看到,for ...in 遍历中,age这个属性没了。
cookie localStorage 和sessionStorage三者之间的区别
ES6 一共有 5 种方法可以遍历对象的属性。
getOwnPropertyNames(obj)
getOwnPropertySymbols(obj)
Reflect.ownKeys(obj)
以上的 5 种方法遍历对象的键名,都遵守同样的属性遍历的次序规则。
首先遍历所有数值键,按照数值升序排列。
其次遍历所有字符串键,按照加入时间升序排列。
最后遍历所有 Symbol 键,按照加入时间升序排列。
Reflect.ownKeys({ [Symbol()]:0, b:0, 10:0, 2:0, a:0 })
['2', '10', 'b', 'a', Symbol()]
ES5的继承
es5// es5 的继承
// 定义父类
function Person(name){
this.name=name
}
// 定义父类的可继承属性与方法
Person.prototype={
name:this.name,
showName:function(){
console.log(this.name)
}
}
// 定义继承函数
function Student(name,grade){
Person.call(this,name)
this.grade=grade
}
Student.prototype=Object.create(Person.prototype)
Student.prototype.showGrade=function(){
console.log(this.grade)
}
// 绑定construct之前,Student.prototype.constructor与Student是不等的
console.log(Student.prototype.constructor==Student) // false
// 打印一下Student.prototype.constructor
console.log(Student.prototype.constructor) // ƒ Object() { [native code] }
// 绑定construct
Student.prototype.constructor=Student
var s1=new Student("小华","高三")
var p1=new Person("小明")
s1.showName() // 小华
s1.showGrade() // 高三
p1.showName() // 小明
ES5中这种最简单的继承,实质上就是将子类的原型设置为父类的实例。
需要经过
1.定义祖先
2.定义祖先可继承的变量/方法
3.定义继承的类(构造函数),并在类中调用组件的方法 call和apply方法
4.使用 prototyoe定义继承关系
5.重新将constructor指向自己
ES5 的继承,实质是先创造子类的实例对象this,然后再将父类的方法添加到this上面(Parent.apply(this))。
ES6的继承
es6// es6的继承
//定义类
class Person {
// constructor方法,就是构造方法
// 如果没有定义构造方法,js会自动为其添加
// constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象 例如: return Object.create({name:"John",age:31})
// new一个类的实例的时候,会立即调用constructor方法
constructor(name){
this.name=name
this.showName=function(){
console.log(this.name)
}
}
// 下面的这个sayHello方法它是不可枚举的,这一点与es5不同
// 需要注意的是,下面的这个sayHello方法不是定义在类Person上的,也不是定义在类的实例对象上的,而是定义在类Person的原型上的
// Person.hasOwnProperty('sayHello') // false
// p1.hasOwnProperty('sayHello') // false
// Person.prototype.hasOwnProperty('sayHello') // true
// p1.__proto__hasOwnProperty('sayHello') // true
sayHello(){
console.log('hello')
}
}
var p1=new Person("xiao8")
console.log(Object.keys(p1)) // ["name", "showName"] 看到没有,sayHello不可枚举,constructor内部定义的变量与方法可枚举
//构造函数的prototype属性,在 ES6 的“类”上面继续存在。
//事实上,类的所有方法都定义在类的prototype属性上面。
console.log(Person===Person.prototype.constructor) // true
//实现继承
class Student extends Person{
constructor(name,grade){
//调用父类的构造函数,用来新建父类的this对象
//super作为函数调用时,返回的是子类B的实例,super内部的this指向B
//super相当于 A.prototype.constructor.call(this)
//super作为函数只能用在constructor中
super(name)
this.grade=grade
}
toString() {
//super作为对象使用时,指向父类的原型对象。
//在静态方法中指向父类
//定义在父类实例上的方法是没办法用的
return this.name + ' ' +super.sayHello();//调用父类的方法
}
}
//可以使用getPrototypeOf方法来获取父类
console.log(Object.getPrototypeOf(Student)===Person) // true
//这里和es5不一样
//对象有属性__proto__,指向该对象的构造函数的原型对象。
//方法除了有属性__proto__,还有属性prototype,prototype指向该方法的原型对象。
var p1 = new Person("Andy");
var s2 = new Student("小华",'三年级');
console.log(p1.__proto__ === p1.__proto__)// true
console.log(s2.__proto__.__proto__ === p1.__proto__) // true
http 状态码解读
网友评论