一.遍历器
遍历就是把容器中的数据都拿出来摆好
而遍历器就是访问容器中数据的工具,是一种方法
1.for:for循环式js中最常用兼容性最好的循环工具,适应绝大部分浏览器,在要求高兼容性的前提下优先选择for循环遍历数组:
var arr=[1,12,3,123]
for(var i=0;i<arr.length;i++){
var re = arr[i]
console.log(re)
}
2.for in:for in 循环主要用于遍历普通对象,i代表对象的key值(第几个对象),obj[i]代表对应的value(对象的值),for in循环遍历的时候会把prototype中的属性遍历出来,所以在使用时最好在循环体内部加一个if(xx.hasOwnProperty(i)){
console.log(xx[i])
}
判断语句,防止访问到prototype上的属性.for in常用于遍历对象,最好不要用来遍历数组,在用for in遍历一个数组后,数组的下标i会变成字符串属性,在进行下标的加减运算时,‘1’+‘1’=‘11’;的情况会导致与预期结果不符.
var obj={name:"jack",age:18,xx:1234};
obj.__proto__={f:1000}
function F() {
this.life = 1
this.money = 100
}
function S(name) {
this.name = name
}
S.prototype = new F()
var s1 = new S("karen")
//原型链上除了系统的成员,它全都访问了
for (var k in s1) {
// console.log(k)
if (s1.hasOwnProperty(k)) { //加入if判断语句,判断是否为自己这一层的属性,避免访问原型对象上的属性
console.log(s1[k])
}
}
3.for Each:通过回调函数调用数组的元素,每一次调用都会把容器中的数据下标和当前数组传进来,打印时可以得到3种数据:el==>arr[index] ; index:数组元素的下标 ; arr:这个数组
- - - - - - - - - - - - - - - - - - - - - - - - - - ?
- - - - - - - - - - - - - - - - - - - - - - - - - 常用
arr.forEach(function(el,index,xx) {
console.log(el,index,xx)
// xx[index]==>el
console.log(this)
})
通过数组调用forEach方法再给里面传一个函数,3个参数分别代表el,index,xx(数组)
!!自己构建一个forEach函数的思想
写在js代码中,自己写一个forEach工具
Array.prototype.myforEach=function (callback) { //这里因为在使用myforEach时,每次都是通过一个数组来调用,所以我们把这个方法写在Array.prototype里,确保每一个数组都能调用到我们写的工具
//这里在通过array调用的形式是这样的:arr.myforEach(function a(){
// console.log(arguments[0]) 这里打印的就是callback里的第一个形参,this[i]
// console.log(arguments[1]) i
// console.log(arguments[2]) this
//})
for (var i=0;i<this.length;i++){ //通过for循环让callback()一直调用数组长度次,达到遍历效果
callback(this[i],i,this])//myforEach执行到这里callback()用小括号再调用到function a.this[i],i,this相当于传进a里的三个实参
}
}
4.map:跟for Each用法相同,也可以得到el,index,arr三种数据,并且给数组中的元素进行改变,改变后的新数据通过return装在数组中
var ar=[100,200,300,400]
① // var ar2=[]
// for(var i=0;i<ar.length;i++){
// ar2.push(ar[i]*ar[i])
// }
var re=ar.map(function(el,index,arr){
// console.log(el,index,arr)
return el*el//这里操作后,ar数组的元素就变成了[100*100,200*200,300*300,400*400]并存储在了re数组中,效果和注释①相同
})
console.log(re)
5.filter():通过数组调用filter()给这个方法传一个函数,用于判断数组中的数据,判断为真时打印为真的那个数据,为假时不打印.有点抽象,看代码
var arr=[12,4,32,4,23,4,23,4,2324,2434,2354]
var re=arr.filter(function(el) { //通过数组调用filter()给这个方法传一个函数
if(el>90){ //进行判断,数组中的元素(el)是否大于90
return true //为真,给返回值一个true,这时大于90的数据就会被打印在一个数组中
}
else{
return false//为假,给返回值一个false,这时小于90的数据不会被打印在数组中
}
})
console.log(re)//打印值为[2324,2434,2354]
当数组中存的数据为对象时一样可以使用,
eg:
var arr = [{
name: "karen1",
rank: 89
}, {
name: "karen2",
rank: 79
}, {
name: "karen3",
rank: 100
}, {
name: "karen4",
rank: 45
}];
var re=arr.filter(function(el) {
if(el.rank>90){return true}
})
console.log(re)//0:{name:"karen3",rank:100}
6.some()方法和every()方法:
这两个方法放一起记:
①some()我的理解为这个就像逻辑短路或(||)数组中如果有一个元素的值满足判断就返回true,都不满足才返回false,遇到一个满足的就不再继续执行了,很像短路或
②every()我理解这个就像逻辑短路与(&&)数组中必须每一个元素的值满足判断才会返回true,有一个不满足就返回false(遇到false后就不继续执行了),遇到满足的还会继续执行直到判断完全部数据,很想短路与
var arr=[1,3,12,3,12,3,12,312,3]
var re=arr.some(function(el) {
// console.log(66)这里只打印了一次用来判断some()在判断完有真后还是否继续执行,不执行
if(el==3){return true}
})
console.log(re)//有为3的数,true
var arr=[90,90,1,2]
var re=arr.every(function(el) {
// console.log(66) 这里打印了两次用来判断some()在判断完有假后还是否继续执行,不执行
if(el>60){
return true
}
})
console.log(re)//false
7.reduce()和reduceRight():
使用效果:把前一次回调函数的返回值,作为下一次回调函数的第一个参数,整个reduce函数的返回值,是回调最后一次调用的返回值;学名斐波那契数列.
reduceRight()只不过是运算时从后往前执行;
这里很抽象,我们代码讲解:
var arr=[1,4,2,3,1,23,123]
var re=arr.reduce(function(n1,n2) {
return n1+n2//第一次n1=1,n2=4,第二次调用时n1=第一次n1+n2=5,n2=2;以此类推
})
console.log(re,arr)//打印结果为157,就是arr数组所有元素值相加得到的
var re2=arr.reduceRight(function (n1,n2) {
console.log(n1,n2)//首次n1=123,n2=23 和reduce()正好相反
return n1+n2
})
console.log(re2)//157
8.for of !!重点
for of时es6的语法,兼容性差一些但是很好用.淘汰了for in方法,
我们代码讲解:
var arr=[{name:"karen",age:18},{name:"karen2",age:182},{name:"karen3",age:183}]
for(el of arr){//el是元素整个部分,这里相当于遍历arr数组中的每一个元素
console.log(el)//{name:"karen",age:18} el代表数组中的元素整体
console.log(el.name)//karen 通过点语法el.name,打印name的属性值
console.log(el.age)//同上
}
var obj={name:"karen",age:18};
for(value of Object.keys(obj)){//value相当于是obj实例对应的值,如:karen,18;Object.keys()代表对象中的实例如:name,age
console.log(obj[value])//打印obj中的value值,即karen,18
console.log(Object.keys(obj));//["name","age"]
}
for of可以很好的遍历数组中的对象,有很多种使用场景
二.对象的检测方法
1.instanceof:
a instanceof b
检测a对象是不是b的类型数据
是就返回true,不是返回false
function Person () {
}
function Student () {
}
Student.prototype=new Person()
var stu1=new Student()
console.log(stu1 instanceof Student)//stu1是不是
console.log(stu1 instanceof Object)//stu1是不是Person这种类型的数据
console.log(stu1 instanceof Array)
2.isPrototypeOf:
用法:a.isPrototypeOf(b),a是不是b的原型对象
function Person () {
}
function Student () {
}
var p1=new Person()
var p2=new Person()
Student.prototype=p1
var stu1=new Student()
console.log(p1.isPrototypeOf(stu1))//t
console.log(p2.isPrototypeOf(stu1))//f
console.log(p2==stu1.__proto__)//f
console.log(p1==stu1.__proto__)//t
3.hasOwnProperty()
用法:a.hasOwnProperty(“b”)
b是不是a自身属性里属性(不能是原型对象上的属性),是就返回true,不是返回false
function Person (name) {
this.name=name
}
function Student () {
this.age=18
}
var p1=new Person("karen")
var p2=new Person("jack")
Student.prototype=p1
var s1=new Student()
// var re=s1.hasOwnProperty("name")
console.log(s1.name,s1.hasOwnProperty("name"))//karen f
console.log(s1,s1.hasOwnProperty("age"))//18 t
console.log(s1.toString,s1.hasOwnProperty("toString"))//f
4.document.querySelectorAll()
用法arr=document.querySelectorAll(“a”)选中所有a放进arr数组里可以用来遍历
<li></li>
<li></li>
<li></li>
<li></li>
<li></li>
<script type="text/javascript">
var arr=document.querySelectorAll("li")
// var arr={0:100,1:200,3:300,length:3}
// console.log(arr,arr.propertyIsEnumerable(0))
for(i in arr){
// console.log(i)//0 1 2 3 4 item length
console.log(i,arr)
if(arr.propertyIsEnumerable(i)){
// arr[i]
console.log(666)
}
}
</script>
5.propertyIsEnumerable()
用法a.propertyIsEnumerable(b)
判断a中的b属性可不可枚举,可以就返回true,不能返回false
var arr=[1,12,3,123]
var arr={0:100,1:200,length:2}
console.log(arr.propertyIsEnumerable(0))//t
console.log(arr.propertyIsEnumerable("length"))//t
for(i in arr){
console.log(i)//0 1 length
}
三.对象的操作
静态方法
静态方法就是直接使用类名的调用方法,比如Object.getOwnPropertyNames(obj),obj是一个对象,且静态方法是无法被字类继承或实例对象拥有的,代码解释一下:
function Person () {
}
Person.say=function () {
console.log(666)
}
function Student () {
}
Student.prototype=new Person()
//这三个都不能调用Person的静态方法
Person.say()//666
Student.say()//报错,不能调用Person的静态方法
1.未知类名时的静态方法使用:
Object.getPrototypeOf()
var xx=document.documentElement//这里我们不知道xx的类名
var re=Object.getPrototypeOf(xx)//通过Object.getPrototypeOf得知xx的类名
console.log(re)//打印除xx的类名
再举个例子:
function person () {
}
function student () {
}
student.prototype=new person()//这里student的prototype就变成了person{}这个空对象
var s1=new student()//这里s1的__proto__为student的prototype,也就是person{}
var re=Object.getPrototypeOf(s1)//我们通过Object.getPrototypeOf()来看s1的__proto__
console.log(re)//打印结果为person{},和我们分析的一致
2.对象未知的情况:
可使用方法
- Object.getOwnPropertyNames()//获得对象的实例名称
- Object.key()//获得对象的实例
- Object.values()//获得对象中实例对应的值
var obj = {
name: "karen",
age: "666"//我们假设这里obj内部的属性我们时不知道的,就可以使用下面的方法来获取了
}
var re=Object.getOwnPropertyNames(obj)
console.log(re)//["name","age"]
var re2=Object.keys(obj)
console.log(re2)//["name","age"]
var re3=Object.values(obj)
console.log(re3)//["karen","666"]
3.Object.defineProperty()
用它来决定一个对象的某些属性是否可修改,或值为多少
var obj = {}
obj.xx = 123
Object.defineProperty(obj, "name1", {
value: "karen",//决定属性的值为多少
writable:false,//true 决定属性的值是否可以被重写
configurable:true, // false 决定属性是否能被删除
enumerable:true // false 决定属性是否能被枚举
})
obj.name1=123
console.log(obj.name1)//writable我们设置为false,所以这里打印karen,不能更改为123
4.Object.create()
我们称这种方法为工厂模式创建,用这种方法是因为主流使用,规范书写格式
eg:
var re=fn("red","200px","div")
function fn () {
var re2={color:"red",size:"200px",name:"div"}
var obj=Object.create(re2)
obj.color=arguments[0]
obj.size=arguments[1]
obj.name=arguments[2]
return obj
}
console.log(re);
打印结果为上图,其实使用起来和obj={}的结果是一样的,但是用Object.create()更加标准
5.Object.getOwnPropertyDescriptors
使用这种方法能够查看对象属性的特性,观察这个对象某个属性的value;writable;configurable;enumerable等
var obj = {}
Object.defineProperty(obj, "age", {
value: "18",
writable: true
})
var re = Object.getOwnPropertyDescriptor(obj, "age")//观察obj对象中age属性的特性
console.log(re)
打印值如上,它可以看到age属性的特性是否可更改
6.Object.preventExtensions()
它让一个对象不可以再添加新的属性
eg:
var obj2 = {
name: "karen1"
}
Object.preventExtensions(obj2)
obj2.age = 100
console.log(obj2)//{name:"karen1"} 这里通过Object.preventExtensions()让obj2不可扩展,所以age属性并没有添加成功