JS8.14 遍历器,对象成员检测,对象的操作

一.遍历器

遍历就是把容器中的数据都拿出来摆好
而遍历器就是访问容器中数据的工具,是一种方法

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.对象未知的情况:
可使用方法

  1. Object.getOwnPropertyNames()//获得对象的实例名称
  2. Object.key()//获得对象的实例
  3. 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属性并没有添加成功
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值