好家伙,本篇为《JS高级程序设计》第八章“对象、类与面向对象编程”学习笔记
工厂模式是另外一种关注对象创建概念的创建模式。
它的领域中同其它模式的不同之处在于它并没有明确要求我们使用一个构造器。
取而代之,一个工厂能提供一个创建对象的公共接口,我们可以在其中指定我们希望被创建的工厂对象的类型。
function createPerson(name,age,job){
let person =new Object();
person.name= name;
person.age =age;
person.job =job;
person.getName = function(){
console.log(this.name);
}
return person;
}
let person_1 = createPerson("panghu","20","student")
person_1.getName();
console.log(person_1);

(看上去没什么问题,但怎么总觉得怪怪的)
let person =new Object();
/...
...
...
../
return person;
前面几章提到过,ECMAScript中的构造函数是用于创建特定类型对象的。
像Object和Array这样的原生构造函数,运行时可以直接在执行环境中使用。
当然也可以自定义构造函数,以函数的形式为自己的对象类型定义属性和方法。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.getName = function () {
console.log(this.name);
};
}
let person_1 = new Person("panghu", "20", "student");
person_1.getName();
console.log(person_1);

在这个例子中,Person()构造函数代替了 createPerson()工厂函数。
实际上,Person()内部的代码跟createPerson()基本是一样的,只是有如下区别。
□没有显式地创建对象。
□属性和方法直接赋值给了this。
□没有return。
另外,要注意函数名Person的首字母大写了。
按照惯例,构造函数名称的首字母都是要大写的,非构造函数则以小写字母开头。
这是从面向对象编程语言那里借鉴的( 是的,非常好的借鉴 ),有助于在ECMAScript中区分构造函数和普通函数。
毕竟ECMAScript的构造函数就是能创建对象的函数。
要创建Person的实例,应使用new操作符。以这种方式调用构造函数会执行如下操作。
(1)在内存中创建一个新对象。
(2)这个新对象内部的[[Prototype]]特性被赋值为构造函数的prototype属性。
(3)构造函数内部的this被赋值为这个新对象(即this指向新对象)。
(4)执行构造函数内部的代码(给新对象添加属性)。
(5)如果构造函数返回非空对象,则返回该对象;否则,返回刚创建的新对象。
2.1.构造函数也是函数
构造函数与普通函数唯一的区别就是调用方式不同。除此之外,构造函数也是函数。
并没有把某个函数定义为构造函数的特殊语法。
任何函数只要使用new操作符调用就是构造函数,而不使用new操作符调用的函数就是普通函数。
function Person(name, age, job) {
this.name = name;
this.age = age;
this.job = job;
this.getName = function () {
console.log(this.name);
};
}
let person_1 = new Person("panghu", "20", "student");
person_1.getName();
//作为函数调用,添加到window对象
Person("xiaofu","20","student")
window.getName();

此处如果将Person当做普通函数来调用,那么this指向的就是全局作用域,数据会被添加到window对象
构造函数虽然有用,但也不是没有问题。
构造函数的主要问题在于,其定义的方法会在每个实例上都创建一遍。
因此对前面的例子而言,person1和person2都有名为sayName()的方法,但这两个方法不是同一个Function 实例。
我们知道,ECMAScript中的函数是对象,因此每次定义函数时,都会初始化一个对象。
如果把方法分离出来,在全局作用域中进行定义,在当前对象需要多个方法,那么就要在全局作用域中定义多个函数.
这个问题可以通过原型模式解决
(他来了,被营销号誉为Js三大难点的"原型"他来了)
理解复杂概念之前我们先从简单的地方入手(比如新华字典)

然后我们知道,原型指的是原来的模型
每个函数都会创建一个prototype属性,这个属性是一个对象,包含应该由特定引用类型的实例共享的属性和方法。
实际上,这个对象就是通过调用构造函数创建的对象的原型。
使用原型对象的好处是,在它上面定义的属性和方法可以被对象实例共享。
原来在构造函数中直接赋给对象实例的值,可以直接赋值给它们的原型,
function Person(){};
Person.prototype.name = "panghu";
Person.prototype.age = "20";
Person.prototype.job = "student";
Person.prototype.getName =function(){
console.log(this.name);
}
let person_1 = new Person();
person_1.getName();
let person_2 = new Person();
person_2.getName();

然后,我们来理解一下这段代码,
首先,我们要把Person的原型当成一个对象来看待,
于是我们现在有了三方势力,Person构造函数,Person原型对象,person_1和person_2两个实例对象

看看这幅图,
Person构造函数Person.prototype指向原型对象,而Person原型对象的constructor指向Person构造函数,
两个实例都只有唯一属性[[Prototype]]指向Person.prototype
在通过对象访问属性时,会按照这个属性的名称开始搜索,搜索开始于对象实例本身
如果在对象实例上找到了,则返回对应的值,如果没找到,则搜索会沿着指针进入原型对象,然后在原型对象上找到属性后,再返回对应的值
function Person(){};
Person.prototype.name = "panghu";
Person.prototype.age = "20";
Person.prototype.job = "student";
Person.prototype.getName =function(){
console.log(this.name);
}
let person_1 = new Person();
person_1.getName();
person_1.name ="xiaofu";
person_1.getName();
delete person_1.name
person_1.getName();

只要给对象实例添加一个属性,这个属性就会遮蔽原型对象上的同名属性,虽然不会修改,但会屏蔽对它的访问

因为从原型上搜索值的过程是动态的,所以即使实例在修改原型之前已经存在,任何时候对原型对象所做的修改也会在实例上反映出来
function Person(){};
Person.prototype.saysomething =function(){
console.log("yes,we can");
}
let person_1 = new Person();
person_1.saysomething();

但重写原型又是另一码事了
function Person() {};
let person_1 = new Person();
Person.prototype = {
constructor: Person,
name: "panghu",
age: "20",
job: "student",
saySomething() {
console.log("yes,we can");
}
}
person_1.saySomething();

虽然随时能给原型添加属性和方法,并能够立即反映在所有对象实例上、但这跟重写整个原型是两回事。
实例的[[Prototype]]指针是在调用构造函数时自动赋值的,这个指针即使把原型修改为不同的对象也不会变。
重写整个原型会切断最初原型与构造函数的联系,但实例引用的仍然是最初的原型。记住,实例只有指向原型的指针,没有指向构造函数的指针。
Person的新实例是在重写原型对象之前创建的。在调用person_1.saySomething()的时候,会导致错误。
这是因为person_1指向的原型还是最初的原型,而这个原型上并没有saySomething属性。

That's all
我有一个模型:classItem项目有一个属性“商店”基于存储的值,我希望Item对象对特定方法具有不同的行为。Rails中是否有针对此的通用设计模式?如果方法中没有大的if-else语句,这是如何干净利落地完成的? 最佳答案 通常通过Single-TableInheritance. 关于ruby-on-rails-Rails-子类化模型的设计模式是什么?,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.co
在railstutorial中,作者为什么选择使用这个(代码list10.25):http://ruby.railstutorial.org/chapters/updating-showing-and-deleting-usersnamespace:dbdodesc"Filldatabasewithsampledata"task:populate=>:environmentdoRake::Task['db:reset'].invokeUser.create!(:name=>"ExampleUser",:email=>"example@railstutorial.org",:passwo
我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i
鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende
给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最
了解Rails缓存如何工作的人可以真正帮助我。这是嵌套在Rails::Initializer.runblock中的代码:config.after_initializedoSomeClass.const_set'SOME_CONST','SOME_VAL'end现在,如果我运行script/server并发出请求,一切都很好。然而,在我的Rails应用程序的第二个请求中,一切都因单元化常量错误而变得糟糕。在生产模式下,我可以成功发出第二个请求,这意味着常量仍然存在。我已通过将以上内容更改为以下内容来解决问题:config.after_initializedorequire'some_cl
我遇到了一个非常奇怪的问题,我很难解决。在我看来,我有一个与data-remote="true"和data-method="delete"的链接。当我单击该链接时,我可以看到对我的Rails服务器的DELETE请求。返回的JS代码会更改此链接的属性,其中包括href和data-method。再次单击此链接后,我的服务器收到了对新href的请求,但使用的是旧的data-method,即使我已将其从DELETE到POST(它仍然发送一个DELETE请求)。但是,如果我刷新页面,HTML与"new"HTML相同(随返回的JS发生变化),但它实际上发送了正确的请求类型。这就是这个问题令我困惑的
我的Rails应用程序中安装了carrierwave。但是,当用户上传多页pdf时,我只希望应用程序获取文档中的第一页并将其转换为jpeg。这可能吗?用什么命令?这是我的uploader。#encoding:utf-8classImageUploader[200,300]##defscale(width,height)##dosomething#end#Createdifferentversionsofyouruploadedfiles:version:thumbdoprocess:resize_to_fill=>[150,210]process:convert=>:jpgdefful
有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|
我在我的Rails项目中使用rspec_rails和factory_girl_railsgem。所有模型都已创建。是否有我可以运行的生成器来为现有模型创建工厂文件?例如:我已经有了一个Blog模型。RSpec允许我通过简单地运行以下命令在spec/models/blog_spec.rb生成一个模型规范文件:railsgeneraterspec:modelblog是否有我可以在命令行中运行的生成器,它会为这个现有模型生成工厂文件,位于:spec/factories/blogs.rb?我在factory_girl_rails中没有看到任何关于发电机的提及文档。