JavaScript初阶(九)---------- 对象的枚举、实参列表arguments
对象的枚举
1. for in循环 (原型链也逃不了)
当我们想把对象的属性一个一个都打印出来的时候,我们就需要用到for in循环
var obj = { name : "hh", age : 20 } for(var prop in obj){ console.log(obj[prop]); }
其中var prop相当于声明变量,in obj,每次循环从obj里面拿出来一个属性名,obj[prop]就可以得到一个一个属性值。注意:如果这里写成obj.prop 或者 obj["prop"],就会打印
undefined, for in循环只针对处理对象,而且是把var prop写在外面
for in循环也有个问题就是他会把自己原型链上的属性都给打印出来,但我们往往只需要他本身的属性,例如:
Person.prototype.size = "big"; function Person() { this.name = "hh"; this.age = 20; } var son = new Person(); for(var prop in son){ console.log(son[prop]); }
所以我们就有了下面的方法。
2.hasOwnProperty ------(可以判断是否是自己的属性)
Person.prototype.size = "big"; function Person() { this.name = "hh"; this.age = 20; } var son = new Person(); for(var prop in son){ if(son.hasOwnProperty(prop)){ console.log(son[prop]); } }
这样就能只打印出自己的属性。
3.in 操作符 (原型链也逃不了)
用来判断属性是否在某个对象中,注意写成字符串的形式。
Person.prototype.size = "big"; function Person() { this.name = "hh"; this.age = 20; } var son = new Person(); if("name" in son){ console.log('yes') } if("size" in son){ console.log('yes') }
4.instanceof 操作符
判断前面的对象是不是后面的构造函数构造出来的。它是用来判断前面的函数的原型链上是否存在于后面的函数的原型。
function Grand() { } Person.prototype = new Grand(); function Person() { } var person = new Person(); person instanceof Person // true [] instanceof Array // true Array instanceof Object // true Object instanceof Array // false
区分数组和对象
利用上面学的部分知识也可以办到
1.instanceof 操作符
Array instanceof Object // true Object instanceof Array // false
2.利用constructor
var obj = {}; var arr = []; console.log(arr.constructor) // function Array() { [ native code] } console.log(obj.constructor) // function Object() { [ native code] }
3.toString方法
因为对象、数组都不能直接用document.write()进行打印,所以系统内部会调用该变量的toString方法。为了方便各种类型的打印,系统在每个原型链上都重写了toString方法。但是我
们需要跳过数组的toString方法,去调用Object上面的toString。这时我们需要使用call来改变this 指向
var obj = { };
var arr = [ ];
var toStr = Object.prototype.toString;
console.log(toStr.call(obj));//[object Object]
console.log(toStr.call(arr));//[object Array]
封装成方法
function isArrayOrObject(target){ var toStr = Object.prototype.toString, arrStr = '[object Array]'; if(toStr.call(target) === arrStr){ return 'this is Array'; }else{ return 'this is Object'; } }
arguments(实参列表)
arguments是每个函数都有的一个对象,他有一个属性叫做callee,指向函数本身。
作用:初始化一个很复杂的东西。
var num = (function(n) { if(n == 1) { return 1; } return n * arguments.callee(n-1); }
1.callee是一个指针,指向拥有这个arguments对象的函数。
我们来看一个栗子:
function ce(num){ if(num <= 1){ //0的阶乘也是1 return 1; } else{ return num*ce(num-1); } } var Ce = ce; ce = function(num){ return 0; }; console.log(Ce(10));
运行之后发现结果就是0,原因就是我们在后边修改了ce,ce()永远返回0,而Ce方法里面调用的就是ce的方法,所以结果是0,解决这个问题用arguments.callee属性
function ce(num){ if(num <= 1){ //0的阶乘也是1 return 1; } else{ return num*arguments.callee(num-1); } } var Ce = ce; ce = function(num){ return 0; }; console.log(Ce(5));
这是输出结果就是120。arguments.callee指向arguments对象的拥有函数引用,当把ce的函数引用赋给Ce后,arguments对象的拥有函数变成了Ce,所以结果是正确的。
2.caller
caller与callee不同,caller属性并不属于arguments对象,它是函数对象的属性,这个属性保存着调用当前函数的函数的引用。
function outer(){ inner(); } function inner(){ console.log(inner.caller); } outer();
让我们来看看运行结果
从结果可知,因为outer()调用了inner(),所以inner.caller就指向outer()。