1、通过原型对象添加属性、方法
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
var p2 = new Person();
alert(p1.name);
alert(p1.sayName==p2.sayName);
结果:输出z3、true
解析:通过构造函数的原型对象添加的属性、方法可以被所有的构造函数实例对象所共享
2、通过构造函数实例对象获得构造函数的原型对象
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
var prototypeObj = Object.getPrototypeOf(p1);
alert(Person.prototype == prototypeObj);
结果:输出true
解析:ECMA5的新特性,根据构造函数的实例对象获得构造函数的实例对象:Object.getPrototypeOf();
3、获取对象的属性执行过程
每次代码读取一个对象的属性的时候, 首先会进行一次搜索:
搜索构造函数的实例对象里name的属性,看看有没有
如果没有,再去构造函数的实例对象所对应的原型对象去搜索name属性,如果有就返回,没有的话则返回undefined
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
alert(p1.name);
结果:输出z4
解析:构造函数的原型对象添加了name属性,紧接着构造函数的实例对象又添加了name属性,根据读取对象属性的原则:
先在构造函数的实例对象查找,如果有直接返回,没有则追溯到构造函数实例对象所对应的原型对象查找,如果有就返回,没有则返回undefined。这里直接在构造函数的实例对象查找到了name属性,所以返回z4。
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
delete p1.name;
alert(p1.name); //就想获得原型对象的name属性
结果:输出z3
4、判断一个某个属性是属于构造函数原型对象的属性还是构造函数实例对象的属性
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
alert(p1.hasOwnProperty("name"));
结果:输出false
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
alert(p1.hasOwnProperty("name"));
结果:输出true
解析:hasOwnProperty(propertyName):用于检测给定的属性在当前对象实例中(而不是原型中)是否存在。
5、in 操作符
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
alert("name" in p1);
结果:输出true
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
alert("name" in p1);
结果:输出true
解析:测试1、测试2都输出了true,说明name属性不管是在构造函数的原型对象还是构造函数的实例对象,只要存在其一,通过in 操作符都会输出true。
6、判断在原型对象中是否存在某个属性
前面通过hasOwnProperty()方法可以判断一个属性是否存在构造函数的实例对象中
通过in 操作符可以判断一个属性是否存在构造函数的原型对象和实例对象中
那么通过hasOwnProperty()方法和in 操作符的结合使用,我们可以自定义一个函数来判断某个属性是否存在构造函数的原型对象当中
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
Person.prototype.hasPrototypeProperty = function hasPrototypeProperty(object,name){ //第一个参数:当前对象 第二个参数:要判断的属性
return !object.hasOwnProperty(name)&&name in object;
};
var p1 = new Person();
p1.name = "z4";
alert(p1.hasPrototypeProperty(p1,"name"));
结果:输出false
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
Person.prototype.hasPrototypeProperty = function hasPrototypeProperty(object,name){
return !object.hasOwnProperty(name)&&name in object;
};
var p1 = new Person();
alert(p1.hasPrototypeProperty(p1,"name"));
结果:输出true
解析:name属性存在构造函数的原型对象中,通过自定义函数先判断object.hasOwnProperty(name)为false,取反后为true,接着name in object为true,二者做与运算,最终结果为true。
该自定义函数可以判断某个属性是否只在构造函数的原型对象中存在。
7、获取构造函数的实例对象的所有属性
ECMA5新特性Object.keys()拿到当前对象即构造函数的实例对象里的所有keys 返回一个数组
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
var attributes = Object.keys(p1);
alert(attributes);
结果:输出空
解析:构造函数的实例对象本身并没有添加任何的属性
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
p1.sex = "男";
var attributes = Object.keys(p1);
alert(attributes);
结果:输出name、sex两个属性
8、获取构造函数的原型对象的所有属性
ECMA5新特性 Object.getOwnPropertyNames 枚举对象所有的属性,不管该内部属性能否被枚举
测试1:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
p1.sex = "男";
var attributes = Object.getOwnPropertyNames(Person.prototype);
alert(attributes);
结果:输出constructor、name、age、sayName
解析:构造函数原型对象本身并没有添加constructor属性,它是每个构造函数的一个内部属性,通过Object.getOwnPropertyNames()方法可以获取到。
测试2:
function Person(){
}
Person.prototype.name = "z3";
Person.prototype.age = 20;
Person.prototype.sayName = function(){
alert("我是原型对象的方法");
}
var p1 = new Person();
p1.name = "z4";
p1.sex = "男";
var attributes = Object.getOwnPropertyNames(p1);
alert(attributes);
结果:输出name、sex
通过Object.getOwnPropertyNames()方法还可以获取到构造函数的实例对象的所有属性,所以Object.getOwnPropertyNames(对象)方法根据不同的参数是可以获取到想对应构造函数原型对象或者构造函数实例对象的所有属性的。
9、模拟Array中each循环方法
原型的另外一个作用就是扩展对象中的属性和方法的
测试1:
var arr = [1,2,3,4,5];
arr.forEach(function(item,index,array){
alert(item);
});
结果:输出1、2、3、4、5
解析:ECMA5对Array新特性的补充,forEach()方法可以遍历迭代数组元素
测试2:
var arr = [1,2,3,4,5,[6,7,8]];
arr.forEach(function(item,index,array){
alert(item);
});
结果:输出1、2、3、4、5、6.7.8
解析:数组Array的forEach()方法只能遍历一维数组
测试3:
下面自己实现一个Array each方法 能遍历多维数组
var arr = [1,2,3,4,5,[6,7,8]];
Array.prototype.each = function(fn){
try{
//1 目的: 遍历数组的每一项 //计数器 记录当前遍历的元素位置
this.i || (this.i=0); //var i = 0 ;
//2 严谨的判断什么时候去走each核心方法
// 当数组的长度大于0的时候 && 传递的参数必须为函数
if(this.length >0 && fn.constructor == Function){
// 循环遍历数组的每一项
while(this.i < this.length){ //while循环的范围
//获取数组的每一项
var e = this[this.i];
//如果当前元素获取到了 并且当前元素是一个数组
if(e && e.constructor == Array){
// 直接做递归操作
e.each(fn);
} else {
//如果不是数组 (那就是一个单个元素)
// 这的目的就是为了把数组的当前元素传递给fn函数 并让函数执行
//fn.apply(e,[e]);
fn.call(e,e);
}
this.i++ ;
}
this.i = null ; // 释放内存 垃圾回收机制回收变量
}
} catch(ex){
// do something
}
return this ;
}
arr.each(function(item){
alert(item);
});
结果:输出1、2、3、4、5、6、7、8
解析:通过数组构造函数的原型对象添加each方法,该方法可以遍历多维数组。
总结:
1、本篇主要讲述了对象的一些常用方法
2、通过构造函数实例对象获得构造函数的原型对象,Object.getPrototypeOf(实例对象)
3、代码读取对象属性的查找过程,先在实例对象查找,找到即返回,如果没有找到,就沿着原型链即通过原型对象一层层向上追溯查找,找到即返回,如果最终都没有查找到则返回undefined。
4、判断某个属性是存在构造函数实例对象还是构造函数的原型对象,
hasOwnProperty(propertyName):用于检测给定的属性在当前对象实例中(而不是原型中)是否存在。
某个属性不管是在构造函数的原型对象还是构造函数的实例对象,只要存在其一,通过in 操作符都会输出true。5、获取构造函数的实例对象的所有属性
Object.keys(构造函数实例对象)返回一个包含实例对象的所有属性数组
Object.getOwnPropertyNames(构造函数的实例对象)返回一个包含实例对象的所有属性数组6、获取构造函数的原型对象的所有属性
Object.getOwnPropertyNames(构造函数的原型对象)返回一个包含原型对象的所有属性数组7、最后模拟了一个数组遍历元素的方法