摘要:动态原型模式是由构造函数和原型模式组合而成的,那么构造函数是怎样的呢这是一个典型的构造函数,通过使用函数,实例化一个对象,那么为什么可以通过使用操作符实例化对象呢,其实在使用操作符的同时,系统会执行以下操作执行函数代码首先默认生成一个对象,
动态原型模式是由构造函数和原型模式组合而成的,那么构造函数是怎样的呢:
function Box(name){ this.name = name; this.call = function(){ alert("your name is "+ this.name) } } var box = new Box("obama");
这是一个典型的构造函数,通过使用new函数,实例化一个box对象,那么为什么可以通过使用new操作符实例化对象呢,其实在使用new操作符的同时,系统会执行以下操作;
var box = new Object(); box.__proto__ = Box.prototype; Box.call(box); //执行函数代码 return box;
首先默认生成一个对象,继承构造函数Box的原型,然后把函数的作用域绑定在这个对象上,在执行函数,最后返回这个对象,因此每个实例对象都是一个独立的对象,我们知道每个对象都是不相等的;
var box1 = new Box("a"); var box2 = new box("a"); box1.call == box2.call //false
原型模式中,
function Bar(){}; Bar.prototype = { constructor:Box, age:100, call:function(){ alert("your age is" + this.age) } }
我们都知道使用字面量的写法,会默认生成Object对象,因此要强制把constructor属性指向Bar,执行的过程是先看自身有没有这个属性,有就执行,不管原型里是否还有,如果没有就继续查找原型,有就执行,没有就报错,如何判断是自身属性还是原型里的属性呢;
var bar = new Bar(); bar.name = "obama"; bar.hasOwnProperty("name"); //true //hasOwnProperty 只会判断自身是否有这个属性,原型是否有无法判断; "name" in bar; //true // in这个方法更近一步能判断不管自身还是原型有属性(当然是可以枚举的属性) //通过这两个方法我们可以判断原型中是否有属性 function isProperty(object,property){ return !object.hasOwnProperty(property) && (property in object); }
重点!!原型是会重写的,这和JS里其他的对象一样,后面的会覆盖前面的,还有个问题是如果原型中修改属性,一个实例对象就会改写这个值,导致其他的实例对象都会改变!!
function Box(){ } Box.prototype = { constructor:Box, boxs:["box1","box2","box3"], name:"bigBox" } var box1 = new Box(); var box2 = new Box(); box1.name = "first box"; console.log(box1.name); //"first box" console.log(box2.name); //"bigbox" box1.boxs.push("box4"); console.log(box1.boxs); //["box1", "box2", "box3", "box4"] console.log(box2.boxs); //["box1", "box2", "box3", "box4"]
很难理解为什么box1修改name属性就不会重写原型,而修改boxs属性就会重写原型,两者的差别就在于一个是赋值,一个是查找,打个比方,
a向b借了100元,那么a就得到了100元,不是a的父亲,爷爷得到了100元,所以赋值即给a添加不论是属性还是方法收益的只有a,不会给a的父亲,爷爷其他人也赋值,但是如果b找a 还的话,如果找不到a就可以找a 的父亲爷爷等其他人,这个意思是是说,只要是赋值,就只作用在赋值对象上,但是查找就不同,可以一直追溯到其他人,上面的例子,
box1.boxs.push(""box4"),可以这么理解,首先是查找,box1.boxs,不然如何push呢,自身属性没有,但是原型上有,有就OK直接操作push,但是这个操作是对象是所有对象共享的,所以一旦修改就改变了!
基于以上的问题,那么动态原型模式就是把共享的使用原型,不共享的使用构造函数,
function Box(){ this.name:"bigBox"; this.boxs = ["box1", "box2", "box3"]; }; Box.prototype = { constructor:Box, num:function(){ console.log(this.boxs.length); } } //或者写在一起 function Box(){ this.name:"bigBox", this.boxs = ["box1", "box2", "box3"]; if(typeof this.run != "function"){ Box.prototype.num = function(){ console.log(this.boxs.length); } } } //因为构造函数执行时,里面的代码都会执行一遍,而原型有一个就行,不用每次都重复,所以仅在第一执行时生成一个原型,后面执行就不必在生成,所以就不会执行if包裹的函数, //其次为什么不能再使用字面量的写法,我们都知道,使用构造函数其实是把new出来的对象作用域绑定在构造函数上,而字面量的写法,会重新生成一个新对象,就切断了两者的联系!
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/85111.html
摘要:可能因为先入为主,在编程之中,往往不由自主地以的逻辑编程思路设计模式进行开发。这是原型模式很重要的一条原则。关于闭包与内存泄露的问题,请移步原型模式闭包与高阶函数应该可以说是设计模式的基础要领吧。在下一章,再分享一下的几种常用设计模式。 前 在学习使用Javascript之前,我的程序猿生涯里面仅有接触的编程语言是C#跟Java——忽略当年在大学补考了N次的C与VB。 从静态编程语言,...
摘要:概括创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。应用方式一分开定义,用来理解构造函数与原型方式二动态原型模式定义,避免独立的构造函数和原型,更完美的定义形式。 概括:创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。 好处:通过这种方式,不仅每个实例都有自己的一份实例属性的副本,而且同时又共享着对方法的引用,最大限度的节省了内存。而且这种混合模式还支...
摘要:组合使用构造函数模式和原型模式创建自定义类型的最常见方式,就是组合使用构造函数模式与原型模式。也就是说,寄生构造函数模式下,构造函数创建的对象与在构造函数外创建的对象没有什么不同。 前言 最近在细读Javascript高级程序设计,对于我而言,中文版,书中很多地方翻译的差强人意,所以用自己所理解的,尝试解读下。如有纰漏或错误,会非常感谢您的指出。文中绝大部分内容引用自《JavaScri...
摘要:通过这种操作,就有了构造函数的原型对象里的方法。你也看到了,就是一个普通对象,所以这种寄生式继承适合于根据已有对象创建一个加强版的对象,在主要考虑通过已有对象来继承而不是构造函数的情况下,这种方式的确很方便。 原文地址在我的博客, 转载请注明出处,谢谢! 标签: [es5对象、原型, 原型链, 继承] 注意(这篇文章特别长)这篇文章仅仅是我个人对于JavaScript对象的理解,并不是...
阅读 2459·2023-04-25 19:31
阅读 2192·2021-11-04 16:11
阅读 2774·2021-10-08 10:05
阅读 1480·2021-09-30 09:48
阅读 2277·2019-08-30 15:56
阅读 2364·2019-08-30 15:56
阅读 2142·2019-08-30 15:53
阅读 2229·2019-08-30 15:44