javascript原型

来源:互联网 发布:淘宝知名的零食店铺 编辑:程序博客网 时间:2024/05/08 22:38

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);//trueconsole.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,两边都没有,返回falseconsole.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);//kkkconsole.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);//使用对象实例无法访问到prototypeconsole.log(box1.__proto__);//使用对象实例访问prototype的指针console.log(Box.prototype);//使用构造函数名访问prototypeconsole.log(box1.constructor==Box);//true//重写了原型对象Box.prototype={age:20//这里不会保留之前原型的任何信息了};console.log(box1.name);//Leeconsole.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);//trueconsole.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:Boxfunction Box(){}Box.prototype={//使用字面量的方式constructor:Box,//强制指向Boxname:'Lee',age:100,run:function(){return this.name+this.age+'运行中....';}};var box = new Box();console.log(box instanceof Box);//trueconsole.log(box instanceof Object);//true//使用构造函数创建原型对象和使用字面量创建原型对象的区别//字面量创建的方式使用constructor属性不会指向实例,而会指向Object,构造函数创建的方式则相反console.log(box.constructor==Box);//trueconsole.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,//强制指向Boxname:'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,//强制指向Boxrun: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框架的话,原型出场的机会不多。不过,学习原型非常有助于理解和学习各种前端框架的源代码,有助于使用前端框架。





1 0