创建模式
在javascript中,主要有以下几种创建模式:
工厂模式
构造函数模式
原型模式
组合模式
动态原型模式
寄生构造函数模式
稳妥构造模式
工厂模式
工厂模式是软件工程领域一种广为人知的设计模式。javascript实现方式:
function createPerson(name, obj, job) { var o = new Object(); o.name = name; o.obj = obj; o.job = job; o.sayName = function() { alert(this.name); } return o; } var person1 = createPerson("Nicholas", 29, "software Enginner"); var person2 = createPerson("Greg", 27, "Doctor");
工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别问题
构造函数模式
function Person(name, age, job) { this.name = name; this.age = name; this.job = name; this.sayName = function () { alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor"); person1 instanceof Person; // true person1 instanceof Object; // true person2 instanceof Person; // true person2 instanceof Object; // true
new操作符实现原理请查看文章附录
不同于工厂模式,构造函数模式
没有显示创建对象
直接将属性和方法赋值给了this对象
没有return语句
解决了对象识别问题
但是构造函数模式同样存在问题,就是每个方法都要在每个实例上重新申明一遍。person1和person2都有一个名为 sayName() 的方法,但那两个方法不是同一个Function实例。(在javascript中,函数实质上也是对象,因此每定义一个函数,也就是实例化一个对象。)
通过吧函数定义转移到构造函数外部可以解决这个问题:
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.sayName = sayName; } function sayName() { alert(this.name); } var person1 = new Person("Nicholas", 29, "Software Engineer"); var person2 = new Person("Greg", 27, "Doctor");
但这种方式又带来了一个新的问题,我们在全局创建了一个全局函数。
需要注意一点,按照惯例,构造函数始终应该以一个大写字母开头,而非构造函数应该以一个小写字母开头。这主要用于区别构造函数和非构造函数,因为构造函数本身也是函数。
原型模式
我们创建的每个函数都有一个 prototype (原型)属性,这个属性是一个指针,指向一个对象,而这个对象的用途可以由特定类型的所有实例共享的属性和方法。
函数原型对象请查看附录
通过原型模式创建对象,我们不必在构造函数中定义对象实例的信息,同时实例化多个对象,每个对象不会再申明一个新的函数。
可以看到, person1.sayName 和 person2.sayName 都指向了同一个函数。
但是原型模式的缺点也是显而易见的。
首先原型模式省略了构造函数模式传递参数这一环节,结果导致所有实例的初始值在默认情况下都是相同的属性值。
更重要的是,因为将属性和方法都放置在原型对象上,实质上原型上的属性是 被所有实例所共享的 。对于包含基本值的属性还表现正常,改变属性值,只是在实例上添加一个同名属性。但对于引用类型值的属性来说,这可能是个灾难。
function Person() {} Person.prototype = { constructor: Person, name: "Nicholas", age: 29, job: "Software Engineer", friends: ["shelby", "Court"], sayName: function() { alert(this.name); } }; var person1 = new Person(); var person2 = new Person(); person1.friends.push("Van"); person1.friends; // ["shelby", "Court", "Van"] person2.friends; // ["shelby", "Court", "Van"]
组合模式
创建自定义类型最常见的方式,就是组合使用构造函数模式和原型模式。构造模式用于定义实例属性,而原型模式用于定义方法和共享属性。
这样,每个实例都会有自己的一份实例属性副本,但同时又共享方法的引用。
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; this.friends = ["Shelby", "Court"]; } Person.prototype.sayName = function() { alert(this.name); } var person1 = new Person("Nicholas", 29, "Software Enginner"); var person2 = new Person("Greg", 27, "Doctor"); person1.friends.push("Van"); person1.firends; // ["Shelby", "Court", "Van"]; person2.firends; // ["Shelby", "Court"] person1.firends === person2.firends; // false person1.sayName === person2.sayName; // true
动态原型模式
function Person(name, age, job) { this.name = name; this.age = age; this.job = job; if (typeof this.sayName != "function") { Person.prototype.sayName = function() { alert(this.name); } } }
寄生构造函数模式
寄生模式的基本概念就是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后再返回新创建的对象。
function Person(name, age, job) { var o = new Object(); o.name = name; o.age = age; o.job = job. o.sayName = function() { alert(this.name); } } var person1 = new Person("Nicholas", 29, "Software Engineer"); person1.sayName(); // "Nicholas"
看起来,除了使用new操作符之外,这个模式和工厂模式其实是一模一样的。
这个模式可以在特殊的情况下用来作为对象创建构造函数。
假设我们需要一个具有额外方法的特殊数组类型。由于不能直接修改Array构造函数,因此可以使用这个模式。
function SpecialArray() { var values = []; values.push.push(values, arguments); values.toPipedString = function() { return this.join("|"); } return values; } var colors = new SpecialArray("red", "blue", "green"); colors.toPipedString(); // "red|blue|green"
该模式主要缺点:
返回的对象和构造函数或构造函数的原型属性间没有关系,不·能依赖instanceof来确定对象类型。
在其他模式能够使用的情况下,尽量不要使用这种模式。
稳妥构造函数模式
function Person(name, age, job) { var o = new Object(); var name = name; var age = age; var job = jbo; o.sayName = function() { alert(name); } } var person1 = Person("Nicholas", 29, "Software Enginner"); firend.sayName(); // "Nicholas"
- 附录
- new 操作符
new操作符实际上会经历4个步骤:
- 创建一个空的简单JavaScript对象(即**{}**);
- 链接该对象(设置该对象的constructor)到另一个对象 ;
- 将步骤1新创建的对象作为**this**的上下文 ;
- 如果该函数没有返回对象,则返回**this**。
function new(func) { var o = {}; o.__proto__ = func.prototype; var result = func.apply(o, arguments); return typeof result === "object" "text-align: center">虽然所有实现都无法直接访问[[Prototype]],但可以通过isPrototype方法来确定对象之间是否存在关系。
我们测试了person1和person2,都返回了true。因为他们内部都有一个指向Person.prototype的指针。
Object.getPrototype()可以返回对象的原型对象。
每当代码读取某个对象的属性时,都会执行一次搜索,目标是具有给定名字的属性。搜索首先会从对象本身开始,如果在实例中找到了对应的属性,则返回该属性的值。如果没找到,则继续搜索指针指向的原型对象。这也是为什么我们在person1和person2两个实例中,并没有定义sayName这个属性,但仍能够正常使用。
我们在调用person1.sayName()是,会执行两次搜索。首先,解析器会问:“实例person1有sayName属性吗?”,答:“没有”。然后他继续搜索,再问:“person1的原型有sayName属性吗?”,答:“有”。于是,它就读取保存在原型中的函数。虽然我们能够通过实例访问原型的属性,但却不能重新原型的属性。
如果我们在实例上添加属性名,而这个属性名又与原型中的属性名相同,即我们希望在实例中重写属性。function Person() {} Person.prototype.name = 'Nicholas'; var person1 = new Person(); var person2 = new Person(); person1.name === person2.name; // true person1.name = 'Greg'; person1.name === person2.name; // false person1.name; // 'Greg' person2.name; // 'Nicholas' person1.__proto__.name; // 'Nicholas'事实上,当我们重写原型属性时,只是在实例上添加了一个新属性。当我们把实例上的属性删除后,又会暴露出原型属性。
delete person1.name; person1.name; // 'Nicholas'使用hasOwnProperty()函数能判断属性是否在实例上。
person1.hasOwnProperty('name'); // false person1.name = 'Greg'; person1.hasOwnProperty('name'); // true以上就是详解 javascript对象创建模式的详细内容,更多关于Java 创建模式的资料请关注其它相关文章!
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]