您的位置:首页 > Web前端 > JavaScript

javascript原型

2016-04-09 19:05 381 查看
1.使用构造函数获取原型属性
//构造函数
function Box(name,age){
this.name = name;//实例属性
this.age = age;
this.run = function(){//实例方法
return this.name+this.age+'运行中...';
}
}
var box1 = new Box();
var box2 = new Box();
console.log(box1.name);
console.log(box1.run());
console.log(box1.run==box2.run);
console.log(box1.prototype);//这个属性是一个对象,访问不到
console.log(box1.__proto__);//这个属性是一个指针指向prototype原型对象
console.log(box1.constructor);//构造属性,可以获取构造函数本身
console.log(box1.constructor==Box);//true
console.log(Box.prototype);//使用构造函数名访问prototype


2.判断一个对象是否指向了该构造函数的原型对象,可以使用isPrototypeOf方法来测试

function Box(){}//声明一个构造函数 构造函数体内什么都没有,如果有,叫做实例属性,实例方法
Box.prototype.name = 'Lee';
Box.prototype.age = 100;
Box.prototype.run = function(){
return this.name+this.age+'运行中....';
};
var box1 = new Box();
var box2 = new Box();
console.log(box1.run==box2.run);//true 方法的引用地址保持一致
//判断一个对象是否指向了该构造函数的原型对象,可以使用isPrototypeOf方法来测试
console.log(Box.prototype.isPrototypeOf(box1));//true


3.原型模式的执行流程:先查找构造函数实例里的属性或方法,如果有,立即返回;如果构造函数实例里没有,则去他的原型对象里找,如果有,就返回。
可以使用hasOwnProperty判断实例中是否存在指定的属性;关于in的使用 不管实例属性或原型属性是否存在,只要有就返回true,两边都没有,返回false。

综合使用hasOwnProperty和in可以判断出某属性是否仅存在于原型中。
使用delete可以删除实例中或原型中的属性。
function Box(){}//声明一个构造函数 构造函数体内什么都没有,如果有,叫做实例属性,实例方法
Box.prototype.name = 'Lee';
Box.prototype.age = 100;
Box.prototype.run = function(){
return this.name+this.age+'运行中....';
};
var box1 = new Box();
var box2 = new Box();
console.log(box1.run==box2.run);//true 方法的引用地址保持一致
//判断一个对象是否指向了该构造函数的原型对象,可以使用isPrototypeOf方法来测试
console.log(Box.prototype.isPrototypeOf(box1));//true
//原型模式的执行流程:
//1.先查找构造函数实例里的属性或方法,如果有,立即返回
//2.如果构造函数实例里没有,则去他的原型对象里找,如果有,就返回
console.log(box1.name);//Lee 原型里的值
//判断实例中是否存在指定的属性
console.log(box1.hasOwnProperty('name'));//false name存在于原型中
box1.name = 'Jack';//实例属性,没有重写原型属性
//判断实例中是否存在指定的属性
console.log(box1.hasOwnProperty('name'));//true name在实例属性中能够找到
//关于in的使用 不管实例属性或原型属性是否存在,只要有就返回true,两边都没有,返回false
console.log('name' in box1);//true 存在实例中或原型中
console.log(box1.name);//Jack 就近原则
console.log(box2.name);//Lee 原型里的值,没有被box1修改
delete box1.name;//删除实例中的属性
console.log(box1.name);//Lee 原型属性
//delete Box.prototype.name;//删除原型中的属性
//console.log('name' in box1);//false name在实例中或原型中都不存在
Box.prototype.name = 'kkk';//覆盖原型中的属性
console.log(box1.name);//kkk
console.log(box1.hasOwnProperty('name'));//false name存在于原型中
//判断只有原型中存在属性
function isProperty(obj,property){
return !obj.hasOwnProperty(property)&&(property in obj);
}
console.log(isProperty(box1,'name'));//true name只在原型中
box1.name = 'Jack';//实例属性,没有重写原型属性
console.log(isProperty(box1,'name'));//false name不只存在于原型中,实例中也有


4.关于原型的重写

function Box(){}//声明一个构造函数 构造函数体内什么都没有,如果有,叫做实例属性,实例方法
Box.prototype.name = 'Lee';
Box.prototype.age = 100;
Box.prototype.run = function(){
return this.name+this.age+'运行中....';
};
var box1 = new Box();
console.log(box1.prototype);//使用对象实例无法访问到prototype
console.log(box1.__proto__);//使用对象实例访问prototype的指针
console.log(Box.prototype);//使用构造函数名访问prototype
console.log(box1.constructor==Box);//true
//重写了原型对象
Box.prototype={
age:20//这里不会保留之前原型的任何信息了
};
console.log(box1.name);//Lee
console.log(box1.run());//正常打印
box1 = new Box();
console.log(box1.name);//undefined
//console.log(box1.run());//报错
console.log(box1.age);//20


5.使用字面量的方式创建原型。使用构造函数创建原型对象和使用字面量创建原型对象的区别:

字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反

//为了让属性和方法更好地体现封装的效果,并且减少不必要的输入,原型的创建可以使用字面量的方式
function Box(){}
Box.prototype={//使用字面量的方式
name:'Lee',
age:100,
run:function(){
return this.name+this.age+'运行中....';
}
};
var box = new Box();
console.log(box instanceof Box);//true
console.log(box instanceof Object);//true
//使用构造函数创建原型对象和使用字面量创建原型对象的区别
//字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反
console.log(box.constructor==Box);//false
console.log(box.constructor==Object);//true


6.如果想让字面量方式的constructor指向实例对象,可以加上constructor:Box

//如果想让字面量方式的constructor指向实例对象,可以加上constructor:Box
function Box(){}
Box.prototype={//使用字面量的方式
constructor:Box,//强制指向Box
name:'Lee',
age:100,
run:function(){
return this.name+this.age+'运行中....';
}
};
var box = new Box();
console.log(box instanceof Box);//true
console.log(box instanceof Object);//true
//使用构造函数创建原型对象和使用字面量创建原型对象的区别
//字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反
console.log(box.constructor==Box);//true
console.log(box.constructor==Object);//false


7.ECMAScript内置的引用类型本身也使用了原型

//ECMAScript内置的引用类型本身也使用了原型
console.log(Array.prototype.sort);//查看sort是否是Array原型对象里的方法
console.log(String.prototype.substring);
String.prototype.addstring = function(){
return this+',被添加了!';//this代表调用的字符串
}
console.log('Lee'.addstring());


8.原型模式创建对象有自己的缺点,他省略了构造函数传参初始化过程,带来的缺点就是初始化的值都是一致的。

原型最大的优点就是共享,原型中的属性被很多实例共享。但是,如果属性包含引用类型,就存在问题。

//原型模式创建对象有自己的缺点,他省略了构造函数传参初始化过程,带来的缺点就是初始化的值都是一致的。
//最大的优点就是共享,原型中的属性被很多实例共享。但是,如果属性包含引用类型,就存在问题
function Box(){}
Box.prototype={//使用字面量的方式
constructor:Box,//强制指向Box
name:'Lee',
age:100,
family:['父亲','母亲','妹妹'],//添加了一个数组属性
run:function(){
return this.name+this.age+this.family;
}
};
var box1 = new Box();
box1.family.push('哥哥');//在第一个实例修改了引用剋行,保持了共享
console.log(box1.run());
var box2 = new Box();
console.log(box2.run());//共享了box1添加后的引用类型的原型


9.为了解决构造传参和共享问题,可以使用组合构造函数+原型模式

//为了解决构造传参和共享问题,可以使用组合构造函数+原型模式
function Box(name,age){//不共享的使用构造函数
this.name = name;
this.age = age;
this.family=['父亲','母亲','妹妹'];
}
Box.prototype={//共享的使用原型模式
constructor:Box,//强制指向Box
run:function(){
return this.name+this.age+this.family;
}
};
var box1 = new Box();
box1.family.push('哥哥');
console.log(box1.run());
var box2 = new Box();
console.log(box2.run());//引用类型没有使用原型,所以没有共享


10.原型模式,不管你是否调用了原型中的共享方法,他都会初始化原型中的方法。

为了解决这一问题,可以将构造函数和原型封装在一起,称为动态原型模式。

//原型模式,不管你是否调用了原型中的共享方法,他都会初始化原型中的方法
//为了解决这一问题,可以将构造函数和原型封装在一起,称为动态原型模式
function Box(name,age){//不共享的使用构造函数
this.name = name;
this.age = age;
this.family=['父亲','母亲','妹妹'];
if(typeof this.run!='function'){//判断run方法是否存在,仅在嗲一次调用时初始化
console.log('第一次初始化');//只会运行1次
Box.prototype.run = function(){
return this.name+this.age+this.family;
};
}
}
var box1 = new Box();
box1.family.push('哥哥');
console.log(box1.run());
var box2 = new Box();
console.log(box2.run());//引用类型没有使用原型,所以没有共享
//使用动态原型模式要注意,不可以使用字面量方式重写原型


11.关于寄生构造函数

寄生构造函数=工厂模式+构造函数模式

//关于寄生构造函数=工厂模式+构造函数模式
function Box(name,age){
var obj= new Object();
obj.name = name;
obj.age = age;
obj.run = function(){
return this.name+this.age+'运行中...';
};
return obj;
}
var box1 = new Box('Lee',100);
var box2 = new Box('Jack',200);
console.log(box1.run());
console.log(box2.run());
//假如要创建一个具有额外方法的引用类型,比较适合使用寄生构造函数
function myString(string){
var str = new String(string);
str.addstring = function(){
return this+',被添加了!';
}
return str;
}
var box = new myString('Lee');
console.log(box.addstring());


12.在一些安全的环境中,比如禁止使用this和new,即构造函数里不使用this,外部实例化构造函数时不适用new。

这种创建方式叫做稳妥构造函数,与寄生构造函数类似。

//在一些安全的环境中,比如禁止使用this和new,即构造函数里不使用this,外部实例化构造函数时不适用new
//这种创建方式叫做稳妥构造函数,与寄生构造函数类似
function Box(name,age){
var obj= new Object();
obj.run = function(){
return name+age+'运行中...';
};
return obj;
}
var box1 = Box('Lee',100);
console.log(box1.run());


综上所述,原型的知识点还是很多的,不过对于一般的程序员来说,不开发自己的js框架的话,原型出场的机会不多。不过,学习原型非常有助于理解和学习各种前端框架的源代码,有助于使用前端框架。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: