JavaScript对象枚举,类数组学习 (四)

对象枚举

for in
当我们遍历一个数组的时候,可以有length方法去获知数组的长度,进而设置循环上限去遍历,可是对象没有length方法,我们就只能利用for in方法去遍历:

obj={
	work:student,
	name = "xxx",
	sex="male",
	proe:123,
}
for (var x in obj){
	console.log(x);
}

程序的结果会是依次输出work,name,sex,proe;当我们想要依次获取属性值的时候,最先想到的一定会是:

for (var x in obj){
	console.log(obj.x);
}

但结果却会超出我们的的预期,他会输出四个undefined,为什么会这样呢?
我们需要知道的是obj.x------>obj[‘x’],这两个语法是相等的,当我们每次对象.属性时,程序就会帮我们做这样的隐式转换。所以在程序中,它会认为是我们在寻找obj对象当中的x属性,没有就会输出undefined,这是新手常常会犯的一个错误。我们只需要将代码改成如下:

for (var x in obj){
	console.log(obj[x]);
}

这样,x就会作为一个变量去使用,而不会再被隐式的转化为字符串了。

hasOwnProperty

这个方法用来判断自己所定义的所有属性/方法,返回值为布尔内型

对象.hasOwnProperty("属性值/方法")

只要是自己所定义的,他都会返回true,即使我们以这样的方式来定义:Object.prototype.abc=123;把属性定义在他的顶级原型中,当我们判断时依旧会返回给我们true,但当我们想要判断顶级原型中的toString()方法,由于是系统自动定义,所以会返回true。

in
ABC in A

这个方法类似于上一个方法,他也用来判断某一属性或方法是否存在于对象,但不同的是,它的搜索范围在整个原型链当中,不管是不是我们自己定义的,只要存在,他就会返回true。

instanceof

这个方法用来判断A的原型链上有没有B的原型。

A instanceof B;

我们就可以用这种方法来判断,对象和数组的区别,[ ] instanceof Array返回的是true,而{ } instanceof Array返回的就会是false。

arguments.callee

callee方法是被定义在arguments对象身上的,用来判断函数的引用,当一些立即执行函数,需要使用递归时,发现它自身是没有函数名的,所以我们就会用到这个方法:

//递归计算100的阶乘
var test = (
	function (n){
	if (n === 1)
		return;
	else
		return n * arguments.callee(n-1);
}(100))

fun.caller

返回当前调用的环境,主要是要区分它和callee方法的不同之处,一个返回当前环境,一个返回函数引用。

克隆

克隆我们也可以称之为复制,把一个对象完全的复制到另一个对象的身上,我们可以利用函数去遍历原始对象,然后用新对象一个一个的去接收原始对象的属性,若属性为原始内型,我们复制的只是表层的数据,但当属性为引用值时,我们复制过来的就将会是引用值得地址,当我们修改原始属性时,复制后对象的相应属性也会受到影响,所以我们要做进一步的优化克隆,编写以下函数来解决上述问题:

obj={
	name:"xxx,
	a:1,
	b:[1,2,3,4],
	c:{
		c1:1,
		c3:3,
		c2:2
	}
};
obj1={};

function Clone(target,origin){
	var target = target || {};
	var toStr = Object.prototype.toString();
	var strRes = "[Object,Array]";
	for (var proe in origin){
		if(origin.hasOwnProperty(proe)){
			if(typeof(origin[proe]) !== 'null' && typeof(origin[proe]) == 'Object'){
				if(toStr.call(origin[proe] == strRes)){
					target[proe] = [];
				}
				else{
					target[proe] = {};
				}
				Clone(origin[proe],target[proe]);
			}
			else{
				target[proe] = origin[proe];
			}
		}
	}
	return target;
}

obj和obj1分别代表被克隆和克隆的两个对象,Clone函数内部主要完成以下几个功能:

  • 若用户未传要接收克隆的对象,则使用{}代替,
  • 判断被克隆对象的自定义属性,并挨个遍历
  • 用typeof来判断当前属性是否为原始内型,并做出相应步骤
  • 判断引用内型的具体内型,根据不同结果,递归再克隆。
    这样克隆出来的对象,就不会再受到原始对象的数据修改的影响。

数组

数组运行存在undefined,当我们**a = [1,2,3,,,4]**这样去定义数组的时候,他会将空缺值自动填补undefined,而不是报错,而且数组运行越界访问,同样会返回undefined,js当中对于数组的检查还是比较松的,一般情况不会报错,他一共有两种定义方式,一种是字面表达式,还有就是创建数组对象去定义,一般的话前者居多。
这里介绍几种关于数组的方法:

改变原数组
  • push方法
    该方法可以在原数组的末尾添加t元素,添加个数不限。
Array.prototype.push = function (target){
	this[this.length] = target;
	this,length++;
}

以上代码为Array原型中的push方法,底层基础有助于我们了解类数组中该如何改变属性值

  • pop方法
    该方法可以在原数组去除最后一个元素。

  • unshift方法
    该方法可以在原数组的最前面依次添加元素,添加个数不限。

  • shift方法
    该方法可以在原数组去除最前面的一个元素。

  • reverse方法
    该方法可以将原数组进行翻转显示。

  • splice方法
    该方法用来切割数组,负数代表倒数元素。最多可以选择三个参数,

    • 第一个参数:选择切割的起点元素
    • 第二个参数:选择切割的个数
    • 第三个参数:选择切割后的填补值
  • sort方法
    该方法用于对于给数组排序,但是如果单纯的以数组名.sort()方法去调用它,结果可能和我们想象的还是有所差异,他会按字符编码去排,但是sort方法允许我们传一个函数去自定义按照我们的想法去排序,具体语法如下:

a = [1,4,-3,4,6,7,2,4,5];
a.sort(
	//当返回值为正数的时候,保持位序不变
	//当返回值为负数的时候,交换两数的位置
	//当返回值为0的时候,保持位序不变
	function (a,b) {
		if(a < b){
			return 1;
		}
		else{
			return -1;
		}
	}
)

以上代码我们定义了一个正序的排序方法,由注释可知如何排序,可根据我们自己定义的返回值去判断,而sort的内部就相当于进行了冒泡排序的算法,一步一步的调用我们所传的这个函数去做判断,当然,代码有可以简化的部分,我们可以直接将函数体改为return a-b;这样数组依旧可以进行正序排序,反之就会进行逆序排序。

  • 分享一个需求小练习
    如果我们需要一个数组每次都以乱序去展示,该如何利用sort方法去实现呢?
    • 其实我们可以利用random随机数和sort配合去使用Math.random()方法每次回返回一个(0,1)范围里的数字,所以我们让它减去0.5,那么这个返回值就可能为负数,也有可能为正数,再将它作为sort参函数的返回值,就能够达到我们的需求。
不改变原数组
  • concat方法
    该方法用于连接两个数组,并将结果返回,不会修改原始数组。
  • join方法
    该方法用于将数组以形参值连接起来转换成字符串进行返回
  • toString方法
    该方法用于将数组转化为字符串进行返回。
  • slice方法
    该方法用于截取数组元素,最多两个参数,截取起始位置到截取结束位置,若参数只有一个,则默认从该位置截取到最后一个。负数代表倒数元素

类数组

一个很像是数组的对象,如我们熟知的argument,它像是数组一样存储了我们的实参,但是数组所拥有的方法它全不具有,所以我们称它为类数组。

var obj = {
 
                "0" : 'a',
 
                "1" : 'b',
 
                "2" : 'c',
 
                "length" : 3,
 
                "push" : Array.prototype.push
 
            }

像这样我们主动给他加上数组所拥有的length属性以及push方法,把他变得更加像一个数组,然后我们就可以调用他的push方法了,在此之前,我们需要了解push方法的实质内涵,才能明白类数组如何去push属性,在前面我们已经提及过,他是要根据length属性的值来添加。他在”2”的后面加了一个”3”:’d’,并且lenngth也变成了四,这些都是一个对象不能具备的东西。
类数组必须有几个组成部分:
类数组最好包含的四个组成部分

  • 属性要为索引(数字)属性
  • 必须有length属性
  • 最好加上push方法
  • “splice” : Array.prototype.splice
分享一个阿里巴巴面试的小练习
28var obj = {
 
                "2" : 'a',
 
                "3" : 'b',
 
                "length" : 2,
 
                "push" : Array.prototype.push,
 
            }
 
            obj.push(obj);

this.length等于2,所以就把a换成c了吧,length等于3,第二次this.length等于2,把d换成d,length+1变成4。

var obj = {
 
                "2" : 'c',
 
                "3" : 'd',
 
                "length" : 2,
 
                "push" : Array.prototype.push,
 
            }
分享一个数组去重的方法

主要思路是利用对象不可能存在重名属性,从数组依次读值,然后去对象中判断是否含有该属性,若没有则定义,若有则说明数组有重值,就可以过滤掉。

Array.prototype.unique=function () {
	var len = this.length,obj = {},arr = [];
	for(var i = 0;i < len;i++){
		if(!obj[this[i]]){
			obj[this[i]] = "xxx";//这里属性值可随意填写
			arr.push(this[i]);
		}
	}
	return arr;
}

当对象内未定义该方法,返回undefined,取非则为true,然后对它进行存储,属性值可以写除0外的任意值,因为当读取属性值返回0,取反,判断仍然为true,所以可能会存在存取误差。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值