JavaScript 原型 - 请澄清

2024-05-15

有人可以帮我理解原型属性吗?我不明白原型属性是函数的属性还是函数内部的属性。

假设我们创建以下构造函数 Food。此时,函数 Food() 具有 Food.prototype 属性。由于 Food 是 Object 的实例,因此这意味着 Obect.prototype 是使用 Food() 创建的所有对象的原型属性。

function Food() {}

然后创建另一个构造函数 Pizza。 Pizza 拥有 Pizza.prototype 属性。

function Pizza(toppings) {
    this.toppings = toppings;
}

然后我们通过将Pizza 的prototype 属性设置为Food 的实例来使Pizza 继承自Food。 Pizza 的原型属性现在是 Food.prototype,因为 Food 是 Pizza 的父级。

Pizza.prototype = new Food();

然后我们创建一个 Pizza 实例

var myPizza = new Pizza("pepperoni");

myPizza 是否也有一个从 Pizza 继承的原型属性?如果是这样,myPizza.prototype == Object.prototype 吗?什么是Obejct.prototype?它是 Object() 的属性吗?只有函数才有原型属性吗? Object.prototype 是一个对象吗? Pizza.prototype 是否指的是创建 Pizza 构造函数的整个函数?这个函数本身是一个对象吗?

function Pizza(toppings) {
    this.toppings = toppings;
}

或者 Pizza.prototype 只是指 Pizza() 范围内的内容?

this.toppings = toppings;

Pizza.toppings 是 Pizza.prototype 的属性吗?但 Pizza.prototype 不是 Pizza() 的属性吗? toppings 仅仅是用 Pizza 构造函数创建的对象的属性吗? Pizza.prototype 是 Pizza 构造函数的属性吗?

目前原型链如下:

myPizza --> Pizza.prototype --> Food.prototype --> Object.prototype


我不会从问题的答案开始,而是从原型和构造函数的工作方式开始,以避免在尝试以部分理解的方式解释这些答案时出现混乱。那么,原型回顾一下:

  • JavaScript 中的每个值,除了null and undefined,有一个关联值:它的原型。

  • 原型用于查找属性。当你评价时x.foo,您检查该值是否x has an 自有财产– 其自身的属性 – 名为“foo”。如果是的话,x.foo是那个的值自有财产。如果没有,则继续查找x的原型。

  • 值的原型可以是null,意味着任何未找到自己财产的财产查找都会导致undefined.

  • 您可以使用该函数获取值的原型Object.getPrototypeOf https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf.

  • 您可以使用以下函数创建具有特定原型的新对象Object.create https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create.

构造函数在 JavaScript 中有一个名为“原型”的属性。该属性的值不是构造函数的原型;而是构造函数的原型。它是用构造函数创建的值的原型。以您的示例构造函数为例:

function Food() {}

如果你跑new Food(),将创建一个新对象,其原型设置为Food.prototype, and Food将被执行this设置为该新对象。换句话说,这个:

// create a new instance of Food
let f = new Food();

与此含义相同:

// create a new object with Food.prototype as its prototype
let f = Object.create(Food.prototype);

// initialize it using the constructor
Food.call(f);

现在,如上所述,属性查找的工作方式产生了一个原型链。如果x有原型y and y没有原型,x.foo在此链上查找:

x -> y -> null
  1. If x有一个自己的属性“foo”,x.foo评估其价值
  2. If y有一个自己的属性“foo”,x.foo评估其价值
  3. 我们已经达到了null,链的末端,所以x.foo is undefined

默认值prototype构造函数的属性是一个新的Object实例,所以a的原型链new Food()看起来像这样:

f -> Food.prototype -> Object.prototype -> null

你可以说一个值x是一个构造函数的实例C if x的原型是C.prototype or x的原型不为 null 并且是一个实例C. (If x is C.prototype, x不是一个实例C.) 这就是instanceof操作员工作原理²:

console.log({} instanceof Object);  // true
console.log(Object.prototype instanceof Object);  // false

你也可以这样说C继承自D if C.prototype是一个实例D.

JavaScript 中内置的所有内容都具有Object.prototype在其原型链上。功能有Object实例:

function f() {}
f instanceof Object  // true

所以构造函数也是:

function Food() {}
Food instanceof Object  // true

值得注意的是,这并没有说明实例之间的关系Food and Object。您可以设置Food.prototype = null to get new Food() instanceof Object === false,但情况仍然会是这样Food instanceof Object.

我希望这个框架足以解决您的问题。无论如何,这就是想法。仍然会明确地使用它来回应他们:

手头的问题

假设我们创建以下构造函数 Food。此时,函数 Food() 具有 Food.prototype 属性。由于 Food 是 Object 的实例,因此这意味着 Obect.prototype 是使用 Food() 创建的所有对象的原型属性。

所有创建的对象new Food()有一个原型Food.prototype。原型为Food.prototype is Object.prototype. Food是一个函数,这意味着它确实是一个实例Object,但相关实例Object这是Food.prototype.

然后我们通过将Pizza 的prototype 属性设置为Food 的实例来使Pizza 继承自Food。 Pizza 的原型属性现在是 Food.prototype,因为 Food 是 Pizza 的父级。

原型property函数的Pizza is now 一个物体与Food.prototype作为它的原型.

myPizza 是否也有一个从 Pizza 继承的原型属性?

myPizza不继承任何东西Pizza。它继承了对象的一切Pizza.prototype. Since Pizza.prototype没有名为“prototype”的属性,myPizza不继承名为“prototype”的属性。

什么是对象原型?它是 Object() 的属性吗?

Object.prototype字面意思是“原型”属性Object”,所以是的。这个值位于所有Object实例的原型链上,这很重要,因为JavaScript中的大多数东西都是Object的实例。除此之外,它就像其他任何东西一样prototype构造函数的属性。

只有函数才有原型属性吗?

使用定义的函数function or class关键字以名为的属性开头prototype。 (箭头函数没有,也不能用作构造函数。)您可以放置​​一个名为prototype在任何事情上。它仅在构造函数上才有意义——与 一起使用的函数new or instanceof.

Object.prototype 是一个对象吗?

当使用“object”来引用任何非原始值时,它是一个带有小写“o”的对象。它不是一个实例Object- 它有一个null原型。

这个函数本身是一个对象吗?

是的,函数就是对象。

Pizza.prototype 是否指的是创建 Pizza 构造函数的整个函数?

No. Pizza.prototype不是一个函数。它由以下人员使用Pizza构造函数但是Pizza构造函数不是它的实例,也不是由它创建的。

或者 Pizza.prototype 只是指 Pizza() 范围内的内容?

也与范围无关。当你评价时new Pizza(), Pizza is called与一个新实例Pizza as its this value. this不是函数的作用域。 “范围”是一些变量集可见的区域。

function Foo() {
    let x = 5;  // a variable in scope. unrelated to `this`.
}
function Foo() {
    this.x = 5;  // assigning to a property of the value `this`.
                 // unrelated to variables.
}

Pizza.toppings 是 Pizza.prototype 的属性吗?

它不是Pizza.toppings。有一个新对象——this– 并且您将参数的值分配给Pizza函数,命名为toppings,到该新对象的属性,也命名为toppings。新对象的原型是Pizza.prototype,但新对象不是Pizza.prototype本身,所以答案是“不”,toppings不是以下的财产Pizza.prototype.

但 Pizza.prototype 不是 Pizza() 的属性吗?

这是一个属性Pizza。 (只是确保Pizza()指的是函数,而不是调用函数得到的值。一定要准确!)

toppings 仅仅是用 Pizza 构造函数创建的对象的属性吗?

Right!

Pizza.prototype 是 Pizza 构造函数的属性吗?

Yes.

目前原型链如下:

myPizza --> Pizza.prototype --> Food.prototype --> Object.prototype

也正确。您可以通过上述内容进行确认getPrototypeOf.

Object.prototype.toString = function () { return 'Object.prototype'; };

function Food() {}
Food.prototype.toString = function () { return 'Food.prototype'; };

function Pizza(toppings) {
    this.toppings = toppings;
}

Pizza.prototype = Object.create(Food.prototype);
Pizza.prototype.toString = function () { return 'Pizza.prototype'; };

let myPizza = new Pizza();
myPizza.toString = function () { return 'myPizza'; };

let chainLink = myPizza;

while (true) {
    console.log(String(chainLink));
    
    if (chainLink === null) {
        break;
    }
    
    chainLink = Object.getPrototypeOf(chainLink);
}

请注意我已经写了Object.create(Food.prototype)代替new Food()这里。你不想在子构造函数之外运行父构造函数,尽管这在 ES3 中很常见。添加了 ES5Object.create。添加ES6class and extends,这就是您在实践中想要使用的。

¹ Primitives don’t have a [[Prototype]] in the spec but that doesn’t really matter because their property lookup and post-ES5 Object.getPrototypeOf work like they do.
² Primitives are strings, booleans, numbers, symbols, null, and undefined. Primitives are immutable – they don’t have any own properties. The distinction between objects and primitives isn’t that important in JavaScript, but because they don’t have any own properties it doesn’t make sense to use them as prototypes. They also don’t count as instanceof anything for what I’m going to claim are historical reasons.
³ By default, that is. You can ask one or all of them not to be with Object.setPrototypeOf. There’s no reason to do this.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JavaScript 原型 - 请澄清 的相关文章

  • 为什么省略分号会破坏这段代码?

    或者换句话说 为什么分号插入失败 导致下面的代码被破坏 function Foo Foo prototype bar function console log bar lt missing semicolon function Foo pr
  • 在有限的上下文中运行 JS 代码

    我正在尝试奔跑trusted 隔离 上下文中的 JS 代码 基本上想出了这个方法 function limitedEval src context return function with this return eval src call
  • 在节点环境中存根 jQuery.ajax (jQuery 2.x)

    我正在尝试运行一些需要存根的测试jQuery ajax 我正在使用 SinonJS 来做到这一点 它曾经与旧版本的 jQuery 1 x 一起工作得很好 var require jquery var sinon require sinon
  • 在上传之前预览图像 VUEjs [重复]

    这个问题在这里已经有答案了 我知道这个问题已经被问过 但我不知道如何在vuejs中使用代码 我尝试了很多但没有任何结果 我还添加了我的代码 有人可以帮帮我吗 这是我的代码 谢谢 html
  • Javascript 进程是否有多个执行线程?

    背景 我正在创建一个 地址簿 类型的应用程序 有很多条目需要加载 一个想法是首先加载一小部分条目 让用户开始 然后将剩余条目排队 优先考虑用户单击的条目 例如 如果他们单击以 X 开头的名称 请先加载这些名称 然后再处理队列的其余部分 这个
  • Javascript 将对象推送为克隆

    我将 d3 用于交互式网络应用程序 我需要绑定的数据在交互过程中发生变化 并且由 JSON 变量中的一些选定对象组成 为此 我在 JSON 变量上使用了映射 并进行了一些查询来选择适当的对象 对象被推送到列表中 并且该列表被绑定为新数据 我
  • 以下文档我无法创建 Vue.js 3 的实例

    The code https stackblitz com edit vue ttt file src main js https stackblitz com edit vue ttt file src main js 问题 我正在尝试在
  • C# 无法覆盖继承的成员

    我正在从一本名为 Chegwidden Gladdis 的书中学习 C 我正在制作与书中编写的相同的程序和相同的代码 但有一个问题 我无法重写父类中的方法 我从章节一开始就读完了这本书 读了五遍 一切都是一样的 但我不明白为什么我不能重写父
  • 使用javascript以编程方式触发iOS safari中的复制菜单?

    我正在尝试实现一种用户友好的方式 将一些文本从文本输入字段复制到 iOS Safari 上的剪贴板 我知道无法在这个平台上以编程方式完成此操作 但我希望能够尽可能地指导用户体验 在 iOS Safari 上 当用户手动突出显示某些文本时 会
  • AngularJS + jQuery 移动

    是否还有其他可能性来设计AngularJS以移动友好的方式应用程序CSS 我正在计划一个移动应用程序 并希望使用 AngularJS 进行逻辑和数据绑定 但我不想自己设计所有内容CSS The AngularJSFAQ说它使用jQuery
  • 如何从 html 页面 [javascript] 调用 Web 服务方法而不刷新页面

    我有一个webservice这将返回一个值 我的要求是 我需要调用它webservice从一个index html页面 该页面有一个 html 提交按钮 在该按钮上单击我正在呼叫JavaScript 从那里我想调用网络方法 我怎样才能做到这
  • node.js 模块/导出系统:是否可以将模块导出为函数

    我想在 Dispatch js 中做这样的事情 function handle msg exports handle 这在调用index js中 var dispatch require Dispatch dispatch data 有任何
  • 轮播滑动(未滑动)事件上的火灾事件,Bootstrap 3

    Bootstrap 2 似乎可以很好地处理幻灯片事件 请参阅这个问题 https stackoverflow com questions 9651466 how to attach slide slid events to the boot
  • 了解 Document.createElement()

    我在用着GWT及其底层DOM能力 我基本上想要实现的是 Have a div包含一些文本的元素 其中一些文本将被包围span元素 span 元素可相互拖动并提供上下文菜单 New span元素可以由最终用户动态创建 它可能是这样的 在应用程
  • Firebase + Node.js:错误:找不到 XMLHttpRequest 兼容性库

    Firebase Node js On iOS 安装的 Node js npm 安装 firebase save 节点测试 js 其中 test js 是一个非常简单的连接到 Firebase 的脚本 var firebase requir
  • 当php脚本通过ajax运行时显示进度条

    我有一个通过 ajax 向服务器提交值的表单
  • Three.js点击单个粒子

    In this example http jsfiddle net agqq96bq 2 您可以看到 2 个可点击的粒子 但它们都受到点击的影响 另外 我只想检测粒子上的点击 而不将它们过滤出场景 像这儿 if intersects len
  • Graphql 将多个查询合并(组合)为一个?

    我正在尝试使用 JavaScript 将多个 GraphQL 查询合并为一个查询 我正在寻找这样的东西 let query3 mergeQueries query1 query2 我们事先不知道哪些查询将被组合 假设我有这样的查询 输入查询
  • 将 html 文本框的值分配给 div 的标题

    line 1
  • JavaScript 阶乘防止无穷大

    我一直在 JavaScript 中使用这个函数来计算阶乘数 var f function factorial n if n 0 n 1 return 1 if f n gt 0 return f n return f n factorial

随机推荐