2、原型对象的另外一个作用就是扩展对象中的属性和方法-----模拟Array中each循环方法//ECMA5新特性 Object.getPrototypeOf(): 根据实例对象获得原型对象
function Person(){}
Person.prototype.name = 'z3';
Person.prototype.age = 20;
Person.prototype.sayName = function(){alert('我是原型对象方法!');};
var p1 = new Person();
//alert(p1.name);//z3
var prototypeObj = Object.getPrototypeOf(p1);
//alert(prototypeObj == Person.prototype);//true
//每次代码读取一个对象属性的时候:首先会进行一次搜索:搜索实例对象里name的属性,看看有没有,如果没有
//再去p2的实例所对应的原型对象里去搜索name属性,如果有就返回,没有返回undefined
var p2= new Person();
p2.name = 'w5';//实例对象的name
//alert(p2.name);//w5 但是我就想获得原型对象的属性 delete p2.name即可
//判断一个对象的属性是属于原型属性还是属于实例属性
var p3 = new Person();
//alert(p3.name);//z3
//alert(p3.hasOwnProperty('name'));//false
//in 操作符: for-in
//判断属性是否存在于实例对象和原型对象中
var p1 = new Person();
alert('name' in p1);//true
var p2 = new Person();
p2.name = 'w3';
//alert('name' in p2);//true
//就是判断一个属性是否存在原型中】
//在原型对象中 是否存在这个属性 第一个参数:当前对象 第二个参数:要判断的属性
/* function hasPrototypeProperty(object,name){
return !object.hasOwnProperty(name) && name in object;
}
var p3 = new Person();
alert(hasPrototypeProperty('p3','name'));//true */
//ECMA5新特性 Object.keys();拿到当前对象所有属性,返回一个数组
var p4 = new Person();
p4.name = 'z3';
p4.age = 20;
var attr = Object.keys(p4);
alert(attr);//name,age
var attr2 = Object.keys(Person.prototype);
alert(attr2);//name,age,sayName
//ECMA5新特性 constructor属性:该属性是不能被枚举的
//Object.getOwnPropertyNames 枚举对象所有属性:不管该内部属性能否被枚举
var attr3 = Object.getOwnPropertyNames(Person.prototype);
alert(attr3);//constructor,name,age,sayName
//简单原型<script type="text/javascript" charset="utf-8">
//Array数组 each方法
//ECMA5 forEach方法 循环遍历数组 只适合遍历一维数组
/* var arr = [1,2,3,[4,[5]]];
arr.forEach(function(item,index,array){
alert(item);
}); */
//自己实现一个Array each方法 能遍历多维数组
var arr = [1,2,3,[4,[5,[6]]]];
Array.prototype.each = function(fn){
try{
//1、遍历数组的每一项
//计数器 记录当前遍历的元素 位置
this.i || (this.i=0);
//2、什么时候去走each核心方法
//当数组的长度大于0的时候 && 传递的参数必须是函数
if(this.length > 0 && fn.constructor == Function){
//循环遍历数组的每一项
while(this.i < this.length){
//获取数组的每一项
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 sth.
}
return this;
};
arr.each(function(item){
alert(item);
});
</script>
//原型的动态性//简单原型
function Person(){}
Person.prototype = {
//constructor: Person, //必须得表示原型对象的构造器
name: 'z3',
age: 20,
job: '程序员',
say: function(){
alert('我是原型函数');
}
};
//ECMA5给原型对象重新设置构造器的方法 Object.defineProperty();
//3个参数, 参数1:重设构造器的对象 参数2:设置什么属性 参数3:options配置项
Object.defineProperty(Person.prototype,'constructor',{
enumerable: false,
value: Person
});
var p1 = new Person();
//alert(p1.name);
//p1.say();
alert(Person.prototype.constructor);//function Object{native code}
for(attr in p1){
alert(attr); //name age job say
}
//原型弊端//原型的动态性
function Person(){
}
var p1 = new Person();
Person.prototype.say = function(){alert('我是方法');};
p1.say();//我是方法
//但是下面的方式会报错
var p2 = new Person();
Person.prototype = {
constructor: Person,
say: function(){alert('我是方法');}
};
p2.say();//error
//组合模式//原型的概念:原型对象里的所有属性和方法 被所有构造函数实例化出来的对象所共享
function Person(){
}
Person.prototype = {
constructor: Person,
name: 'z3',
age: 20,
job: '程序员',
friends: ['lisi','wangwu'],
say: function(){alert('我的名字');}
};
var p1 = new Person();
var p2 = new Person();
p1.friends.push('zhaoliu');
alert(p1.friends);//lisi,wangwu,zhaoliu
alert(p2.friends);//lisi,wangwu,zhaoliu
//原型里的属性和方法 被所有对象所共享:static
//两种模式//组合使用原型和构造函数式(定义一个类 开发时常用的方式)
function Person(name,age,friends,job){
this.name = name;
this.age = age;
this.friends = friends;
this.job = job;
}
Person.prototype = {
constructor: Person,
sayName: function(){
alert(this.name);
}
};
var p1 = new Person('z3',20,['王五','赵六'],'技术总监');
var p2 = new Person('z4',25,['王五','赵七'],'boss');
alert(p1.friends);//王五,赵六
alert(p2.friends);//王五,赵七
4、三种继承方式<script type="text/javascript" charset="utf-8">
//动态原型模式: 让你的代码都封装到一起
function Person(name,age,friends,job){
this.name = name;
this.age = age;
this.friends = friends;
this.job = job;
//动态原型模式
if(typeof this.sayName != 'function'){
Person.prototype.sayName = function(){
alert(this.name);
};
}
}
//稳妥构造函数式: durable object(稳妥对象) 非常安全的环境中
//1、没有公共属性 2、不能使用this对象
function Person(name,age,job){
//创建一个要返回的对象
var obj = new Object();
//可以定义一些私有的变量和函数
var name = name;
var sex = 'm';
var saySex = function(){};
//添加一个对外的方法
obj.sayName = function(){
alert(name);
};
return obj;
}
var p1 = new Person('z3');
p1.sayName();//z3
</script>
<script type="text/javascript" charset="utf-8">
//js中实现继承:采用原型链的概念
//构造函数 原型对象 实例对象
//构造函数.prototype = 原型对象
//原型对象.constructor = 构造函数的(模板)
//原型对象.isPrototypeOf(实例对象) 判断实例对象的原型是不是当前对象
//构造函数 实例对象 (类和实例)
//父类的构造函数
function Sup(name){
this.name = name;
}
//父类的原型对象
Sup.prototype = {
constructor: Sup,
sayName: function(){alert(this.name);}
};
//子类构造函数
function Sub(age){
this.age = age;
}
//如果我们让子类的原型对象等于父类的实例,结果会怎样?(实现了js的继承)
//1、显然此时的原型对象将包含一个指向另一个原型的指针
//sup的实例对象和sup的原型对象有一个关系
//2、相应的另一个原型中也包含着一个指向另一个构造函数的指针
//子类的原型对象的构造器变成了父类的构造器
Sub.prototype = new Sup('z3');
alert(Sub.prototype.constructor);//function Sup(){native code}
var sub1 = new Sub();
alert(sub1.name);//z3
sub1.sayName();//z3 */
//原型继承
//原型继承的特点:即继承了父类的模板,又继承了父类的原型对象
/* //父类
function Person(name,age){
this.name = name;
this.age = age;
}
//父类的原型对象属性
Person.prototype.id = 10;
//子类
function Boy(sex){
this.sex = sex;
}
Boy.prototype = new Person('z3');
var b = new Boy();
alert(b.name);//z3
alert(b.id);//10
//类继承 只继承模板,不继承原型对象
//父类
function Person(name,age){
this.name = name;
this.age = age;
}
//父类的原型对象属性
Person.prototype.id = 10;
//子类
function Boy(name,age,sex){
//call apply
Person.call(this,name,age);
this.sex = sex;
}
var b = new Boy('z3',20,'m');
alert(b.name);//z3
alert(b.age);//20
alert(b.id);//undefined 父类的原型对象并没有继承
//原型继承+借用构造函数继承 = 混合继承
//父类
function Person(name,age){
this.name = name;
this.age = age;
}
//父类的原型对象属性
Person.prototype.id = 10;
Person.prototype.sayName = function(){alert(this.name);};
//子类
function Boy(name,age,sex){
//call apply
Person.call(this,name,age);//1、借用构造函数继承
this.sex = sex;
}
//2、原型继承
//只剩下父类的实例和父类的原型对象的关系了
Boy.prototype = new Person();//继承父类的原型对象
var b = new Boy('z3',20,'m');
alert(b.name);//z3
alert(b.sex);//m
b.sayName();//z3
</script>