草庐IT

javascript - Javascript 中的对象类型

coder 2025-02-16 原文

这是一个来自学习阶段新手的相当普遍的问题,是我需要澄清的问题。

我目前正在学习对象,此时我正在学习继承。在本课的这一点上,我已经学习了几种不同的创建对象的方法,但使用 this 来创建对象。关键字似乎具有最多的功能:

function Person(){
    this.eyes = 2;
    this.ears = 2;
    this.arms = 2;
    this.hands = 2;
    this.feet = 2;
    this.legs = 2;
    this.species = "Homo sapien";
    }

我明白我可能会用它做什么,但是有一个对象是这样创建的:
var person = new Object();
person.eyes = 2;
person.ears = 2;
person.arms = 2;
person.hands = 2;
person.feet = 2;
person.legs = 2;
person.species = "Homo sapien";

因为我似乎可以用前者做我不能用后者做的事情,所以我想知道是否有任何理由不一直使用前一种方法。谁能帮我解决这个问题?我不需要很长的详细答案(尽管有人会很感激)。这只是我想摆脱的一个问题,这样我就不会纠缠于此。

最佳答案

前言 :如果您不确定我下面的“原型(prototype)”一词是什么意思,请跳到分隔符下方进行解释,然后再回到答案的顶部。 :-)

假设在您的第一个示例中,您然后调用 Person通过 new :

var person = new Person();

...那么唯一的区别 person使用第二个示例获得的那个与继承有关:通过 new Person 创建的那个在 Person.prototype 上分配对象作为其底层原型(prototype)。

I'm wondering if there's any reason why I wouldn't just use the former method all the time



如果您不需要使用原型(prototype),那么使用构造函数可能会变得不必要地复杂。请注意,您的第二种形式可以更简洁地编写:
var person = {
    eyes: 2,
    ears: 2,
    arms: 2,
    hands: 2,
    feet: 2,
    legs: 2,
    species: "Homo sapien"
};

这称为对象初始值设定项:它使用您看到的列出的属性创建一个新对象。永远不需要使用 x = new Object() ;如果你想要一个新的空白对象,只需使用 x = {}; .

当一个对象是一次性的时,直接创建它通常是创建它的最简单方法。

构造函数的主要优势在于它们是基本相似对象的工厂:具有相同的初始属性集,具有相同的底层原型(prototype)等。并且该函数可以接受参数并使用它们来装备它正在创建的对象以适当的方式,也许对构造参数等进行一些验证。也就是说:它们集中了初始化逻辑。

构造函数并不是拥有函数工厂的唯一方法。你也可以这样做:
function buildPerson() {
    return {
        eyes: 2,
        ears: 2,
        arms: 2,
        hands: 2,
        feet: 2,
        legs: 2,
        species: "Homo sapien"
    };
}
var person = buildPerson();

如果你想让那个人有一个原型(prototype)(ES5 浏览器和更高版本):
var personPrototype = {
    // ...properties for the person prototype...
};
function buildPerson() {
    var obj = Object.create(personPrototype);
    obj.eyes = 2;
    obj.ears = 2;
    obj.arms = 2;
    obj.hands = 2;
    obj.feet = 2;
    obj.legs = 2;
    obj.species = "Homo sapien";
    return obj;
}
var person = buildPerson();

(还有另一种更详细的方法来定义这些属性。)

JavaScript 非常灵活。 :-)

“原型(prototype)”

JavaScript 使用原型(prototype)继承,这是一种奇特的方式,表示对象 A 可以由对象 B“支持”,这样如果您向 A 请求它没有的属性,JavaScript 引擎将查看该属性是否存在在 B. 一个快速的实际例子:
var proto = {
    name: "proto's name"
};
var obj = Object.create(proto); // Creates an object backed by the given prototype

不用担心 Object.create ,现在你只需要知道它会创建一个新对象并根据你传递给它的对象分配它的底层原型(prototype)。所以objproto 支持.
obj没有 name属性(property),但如果我们这样做:
console.log(obj.name);

...我们看到"proto's name" .那是因为当 JavaScript 引擎试图获取 name 时来自 obj 的值,发现 obj没有 name属性,所以它看了obj的原型(prototype),proto .在那里找到它后,它使用了来自 proto 的值。 .

只有在获取值时才会发生这种情况(除了在某些高级情况下我们现在可以忽略)。设置属性值时,它会在您设置它的对象上设置。所以:
var proto = {
    name: "proto's name"
};
var obj = Object.create(proto); // `obj` is backed by `proto`
console.log(obj.name);          // "proto's name"
obj.name = "obj's name";
console.log(obj.name);          // "obj's name"

原型(prototype)的目的是重用,因此一个对象可以是其他几个对象的原型(prototype)也就不足为奇了:
var proto = {
    name: "proto's name"
};
var a = Object.create(proto);   // `a` is backed by `proto`
var b = Object.create(proto);   // `b` is also backed by `proto`
console.log(a.name);            // "proto's name"
console.log(b.name);            // "proto's name"
a.name = "a's name";
console.log(a.name);            // "a's name"
console.log(b.name);            // "proto's name"

原型(prototype)对象是普通对象;我们可以改变它们:
var proto = {
    name: "proto's name"
};
var obj = Object.create(proto);
console.log(obj.name);          // "proto's name"
proto.name = "updated";
console.log(obj.name);          // "updated"

obj没有自己的 name属性,每次我们访问它时,JavaScript 引擎都会查看它的原型(prototype)。
new运算符自动为它创建的对象分配一个原型(prototype):它使用函数的 prototype 的对象。属性有它。所以:
function Person(name) {
    this.name = name;
}
Person.prototype.sayName = function() {
    console.log("My name is " + this.name);
};
var p = new Person("Fred"); // Creates an object backed by Person.prototype,
                            // then calls Person with this referring to the
                            // object
p.sayName();                // "My name is Fred";

最后:由于原型(prototype)对象是普通对象,它们也可以有原型(prototype):
var rootProto = {
    name: "root proto's name"
};
var middleProto = Object.create(rootProto);
middleProto.middleProp = "middle property";
var obj = Object.create(middleProto);
console.log(obj.name);       // "root proto's name"
console.log(obj.middleProp); // "middle property"

对于 name ,JavaScript 引擎查看 obj ,没有看到 name属性(property),所以看着 middleProto .它没有看到 name属性也存在,所以它看起来是 rootProto .它在那里找到它,所以它使用它。

困惑点:很多人对构造函数的属性被称为prototype这一事实感到困惑。并认为它是函数的原型(prototype)。不是。它只是函数对象的一个​​普通属性(函数是对象并且可以有属性)。 只有它的特别之处在于 new当您通过 new 调用函数时使用它.非函数对象没有 prototype属性,它们的原型(prototype)不是普通属性,而是内部事物。您可以通过将对象的原型(prototype)传递给 Object.getPrototypeOf 来获取对象的原型(prototype)。 :
var proto = {/*...*/};
var obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true

关于javascript - Javascript 中的对象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32076090/

有关javascript - Javascript 中的对象类型的更多相关文章

  1. ruby - 如何从 ruby​​ 中的字符串运行任意对象方法? - 2

    总的来说,我对ruby​​还比较陌生,我正在为我正在创建的对象编写一些rspec测试用例。许多测试用例都非常基础,我只是想确保正确填充和返回值。我想知道是否有办法使用循环结构来执行此操作。不必为我要测试的每个方法都设置一个assertEquals。例如:describeitem,"TestingtheItem"doit"willhaveanullvaluetostart"doitem=Item.new#HereIcoulddotheitem.name.shouldbe_nil#thenIcoulddoitem.category.shouldbe_nilendend但我想要一些方法来使用

  2. ruby - 其他文件中的 Rake 任务 - 2

    我试图在一个项目中使用rake,如果我把所有东西都放到Rakefile中,它会很大并且很难读取/找到东西,所以我试着将每个命名空间放在lib/rake中它自己的文件中,我添加了这个到我的rake文件的顶部:Dir['#{File.dirname(__FILE__)}/lib/rake/*.rake'].map{|f|requiref}它加载文件没问题,但没有任务。我现在只有一个.rake文件作为测试,名为“servers.rake”,它看起来像这样:namespace:serverdotask:testdoputs"test"endend所以当我运行rakeserver:testid时

  3. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  4. ruby-on-rails - Rails 3 中的多个路由文件 - 2

    Rails2.3可以选择随时使用RouteSet#add_configuration_file添加更多路由。是否可以在Rails3项目中做同样的事情? 最佳答案 在config/application.rb中:config.paths.config.routes在Rails3.2(也可能是Rails3.1)中,使用:config.paths["config/routes"] 关于ruby-on-rails-Rails3中的多个路由文件,我们在StackOverflow上找到一个类似的问题

  5. ruby-on-rails - 按天对 Mongoid 对象进行分组 - 2

    在控制台中反复尝试之后,我想到了这种方法,可以按发生日期对类似activerecord的(Mongoid)对象进行分组。我不确定这是完成此任务的最佳方法,但它确实有效。有没有人有更好的建议,或者这是一个很好的方法?#eventsisanarrayofactiverecord-likeobjectsthatincludeatimeattributeevents.map{|event|#converteventsarrayintoanarrayofhasheswiththedayofthemonthandtheevent{:number=>event.time.day,:event=>ev

  6. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  7. ruby-on-rails - Rails 3.2.1 中 ActionMailer 中的未定义方法 'default_content_type=' - 2

    我在我的项目中添加了一个系统来重置用户密码并通过电子邮件将密码发送给他,以防他忘记密码。昨天它运行良好(当我实现它时)。当我今天尝试启动服务器时,出现以下错误。=>BootingWEBrick=>Rails3.2.1applicationstartingindevelopmentonhttp://0.0.0.0:3000=>Callwith-dtodetach=>Ctrl-CtoshutdownserverExiting/Users/vinayshenoy/.rvm/gems/ruby-1.9.3-p0/gems/actionmailer-3.2.1/lib/action_mailer

  8. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  9. ruby-on-rails - 如何验证非模型(甚至非对象)字段 - 2

    我有一个表单,其中有很多字段取自数组(而不是模型或对象)。我如何验证这些字段的存在?solve_problem_pathdo|f|%>... 最佳答案 创建一个简单的类来包装请求参数并使用ActiveModel::Validations。#definedsomewhere,atthesimplest:require'ostruct'classSolvetrue#youcouldevencheckthesolutionwithavalidatorvalidatedoerrors.add(:base,"WRONG!!!")unlesss

  10. ruby-on-rails - form_for 中不在模型中的自定义字段 - 2

    我想向我的Controller传递一个参数,它是一个简单的复选框,但我不知道如何在模型的form_for中引入它,这是我的观点:{:id=>'go_finance'}do|f|%>Transferirde:para:Entrada:"input",:placeholder=>"Quantofoiganho?"%>Saída:"output",:placeholder=>"Quantofoigasto?"%>Nota:我想做一个额外的复选框,但我该怎么做,模型中没有一个对象,而是一个要检查的对象,以便在Controller中创建一个ifelse,如果没有检查,请帮助我,非常感谢,谢谢

随机推荐