原型还是内联,有什么区别?

2023-11-25

我刚刚学习 Javascript,我想知道是否使用原型声明,如下所示:

function TSomeObj()
{
  this.name="my object";
}

TSomeObj.prototype.showname = function() {
  alert(this.name);
}

基本上和这样做是一样的:

function TSomeObj()
{
  this.name="my object";
  this.showname = function() {
    alert(this.name);
  }
}

当我转储对象的属性时,我得到相同的结果:

TSomeObj (inline version) =
{ 
    'name': 'my object',
    'test': function
}

TSomeObj (prototype declaration) =
{ 
    'name': 'my object',
    'test': function
}

使用原型声明到底有什么好处?也许除了更少的混乱和更有序的源代码。

更新:我也许应该更清楚地表明这是final结果我很好奇。最终结果当然是相同的(即都在对象原型中注册一个新函数) - 但它们的方式却截然不同。感谢您的所有回复和信息!


注意:这个答案是准确的,但并没有完全反映使用 ES6 在 JavaScript 中创建类的新方法class Thing {}句法。这里的所有内容实际上都适用于 ES6 类,但可能需要一些翻译。

我最初回答了错误的问题。这是您实际提出的问题的答案。我会留下我的其他笔记,以防它们对某人有帮助。

通过在构造函数中向对象添加属性this.prop与在外面这样做不同Object.prototype.prop.

  1. 最重要的区别是,当您将属性添加到函数的原型并从中实例化一个新对象时,该属性是通过逐步继承链在新对象中访问的,而不是直接在对象上访问。

     var baseobj = {};
     function ObjType1() {
        this.prop = 2;
     }
     function ObjType2() {}
     ObjType1.prototype = baseobj;
     ObjType2.prototype = baseobj; // these now have the *same* prototype object.
     ObjType1.prototype.prop = 1;
     // identical to `baseobj.prop = 1` -- we're modifying the prototype
    
     var a = new ObjType1(),
       b = new ObjType2();
     //a.hasOwnProperty('prop') : true
     //b.hasOwnProperty('prop') : false -- it has no local property "prop"
     //a: { prop = 2 }, b : { prop = 1 } -- b's "prop" comes from the inheritance chain
    
     baseobj.prop = 3;
     //b's value changed because we changed the prototype
     //a: { prop = 2 }, b : { prop = 3 }
    
     delete a.prop;
     //a is now reflecting the prototype's "prop" instead of its own:
     //a: { prop = 3 }, b : { prop = 3 }
    
  2. 第二个区别是,向原型添加属性会在代码执行时发生一次,但向构造函数内的对象添加属性会在每次创建新对象时发生。这意味着使用原型性能更好并且使用更少的内存,因为在叶/邻近对象上设置相同的属性之前不需要新的存储。

  3. 另一个区别是内部添加的函数可以访问私有变量和函数(在构造函数中声明的变量和函数var, const, or let),而基于原型或外部添加的函数则不然,只是因为它们的作用域错误:

     function Obj(initialx, initialy) {
        var x = initialx,
           y = initialy;
        this.getX = function() {
           return x;
        }
        var twoX = function() { // mostly identical to `function twoX() { ... }`
           return x * 2;
        }
        this.getTwoX = function() {
           return twoX();
        }
     }
    
     Obj.prototype.getY = function() {
        return y; // fails, even if you try `this.y`
     }
     Obj.prototype.twoY = function() {
        return y * 2; // fails
     }
     Obj.prototype.getTwoY = function() {
        return twoY(); // fails
     }
    
     var obj = new Obj();
     // obj.y : fails, you can't access "y", it is internal
     // obj.twoX() : fails, you can't access "twoX", it is internal
     // obj.getTwoX() : works, it is "public" but has access to the twoX function
    

有关 JavaScript 对象、函数和继承的一般说明

  1. JavaScript 中的所有非字符串和非标量变量都是对象。 (某些基本类型在使用方法时会进行装箱,例如true.toString() or 1.2.valueOf())。它们的行为都有点像哈希/字典,因为它们具有可以分配给它们的无限(?)数量的键/值对。 JavaScript 中当前的原语列表是: string、number、bigint、boolean、undefined、symbol、null。

  2. 每个对象都有一个“原型”继承链,一直延伸到基础对象。当您访问对象的属性时,如果该属性在对象本身上不存在,则检查该对象的秘密原型,如果不存在,则检查该对象的原型,依此类推。一些浏览器通过属性公开这个原型__proto__。获取对象原型的更现代的方法是Object.getPrototypeOf(obj)。常规对象没有prototype属性,因为该属性用于函数,用于存储该对象will be使用该函数作为构造函数创建的任何新对象的原型。

  3. JavaScript 函数是对象的一种特殊情况,除了具有对象的键/值对之外,还具有参数和一系列按顺序执行的语句。

  4. 每次调用函数对象时,它都会与通过关键字从函数内部访问的另一个对象配对this。通常,this对象是函数所属的对象。例如,''.replace()将字符串文字装箱为String,然后在替换函数中,this指的是那个对象。另一个例子是当一个函数附加到 DOM 元素时(可能是按钮上的 onclick 函数),那么this指的是 DOM 元素。您可以手动选择配对this对象动态使用apply or call.

  5. 当使用 JavaScript 函数调用时new关键字如var obj = new Obj(),这会导致特殊的事情发生。如果您没有专门返回任何内容,那么而不是obj现在包含返回值 of the Obj函数,它包含这个对象在调用时与该函数配对,这将是一个新的空对象,其继承链中的第一个父对象设置为Obj.prototype。被调用的Obj()函数在运行时可以修改新对象的属性。然后返回该对象。

  6. 您不必太担心关键字constructor,只要这么说就够了obj.constructor指向 Obj 函数(这样您就可以找到创建它的东西),但您可能不需要在大多数情况下使用它。

回到你的问题。要了解从构造函数内修改对象属性和修改其原型之间的区别,请尝试以下操作:

var baseobj = {prop1: 'x'};
function TSomeObj() {
   this.prop2 = 'y';
};
TSomeObj.prototype = baseobj;
var a = new TSomeObj();
//now dump the properties of `a`
a.prop1 = 'z';
baseobj.prop1 = 'w';
baseobj.prop2 = 'q';
//dump properties of `a` again
delete a.prop1;
//dump properties of `a` again

你会看到这个设置a.prop1实际上是创建邻近对象的新属性,但它不会覆盖基础对象的 prop1。当您删除时prop1 from a然后你就得到了继承的prop1我们改变了。另外,即使我们添加了prop2 after a被创建,a仍然拥有该属性。这是因为 javascript 使用原型继承而不是经典传承。当你修改原型时TSomeObj您还可以修改所有先前实例化的对象,因为它们正在主动继承它。

当您用任何编程语言实例化一个类时,新对象将具有其“构造函数”类(我们通常认为与该对象同义)的属性。在大多数编程语言中,您无法更改类或实例化对象的属性或方法,除非停止程序并更改类声明。

不过,Javascript 允许您修改对象的属性and运行时的“类”,并且该类型类的所有实例化对象也会被修改,除非它们有自己的属性来覆盖修改。对象可以生成对象,对象也可以生成对象,因此它以一条链的方式一直运行到基础Object班级。我将“类”放在引号中是因为 JavaScript 中确实不存在类这样的东西(即使在 ES6 中,它也主要是语法糖),除了new关键字允许您使用连接的继承链创建新对象,因此我们将它们称为类,即使它们只是使用构造函数调用的结果new关键词。

其他一些注意事项:函数有一个Function构造函数,对象有一个Object构造函数。原型为Function构造函数是(惊喜,惊喜)Object.

在没有运行构造函数的情况下从对象继承

在某些情况下,能够在不运行构造函数的情况下创建新的“对象实例”很有用。您可以从类继承,而无需像这样运行类的构造函数(几乎就像手动执行child.__proto__ = parent):

function inheritFrom(Class) {
   function F() {};
   F.prototype = Class.prototype;
   return new F();
}

现在更好的方法是Object.setPrototypeOf().

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

原型还是内联,有什么区别? 的相关文章

  • jQuery mobile 中的文本区域高度和宽度?

    我修复了 jQuery mobile 中文本区域元素的高度 并且在纵向中得到了完美的高度和宽度 但在横向中宽度没有放大 谁能帮我 提前致谢 HTML
  • JavaScript 添加布尔值

    console log true true 2 console log typeof true true number console log isNaN true true false 为什么两个布尔类型相加会产生一个数字 我有点理解 如
  • 从函数返回函数的目的是什么?

    阅读一些遗留代码 发现 A prototype setSize function var v1 new Vector2 return function size var halfSize v1 copy size multiplyScala
  • 如何正确清理来自 AngularJS 控制器的无效输入的表单?

    我有一个 AngularJS 表单 其中包含 除其他字段之外 类型之一url 后者很重要 因为这会强制相应的输入成为有效的 URL 在某些条件下 例如 要关闭具有此类表单的模式对话框 我想以编程方式清除该表单 为此 我实现了方法reset基
  • 使用 Angular 指令禁用文本选择

    我正在学习 JavaScript 和 AngularJS 我想使用 Angular Directive 禁用文本选择 我有该函数的 JavaScript 代码 function clearSelection if document sele
  • 如何使用有角度的材料创建卡片网格?

    我正在尝试使用 ng repeat 创建每行三张卡片的网格 我有一个普通的 javascript 对象数组附加到范围 下面的代码将为每张卡创建一个新行 div div
  • 想要动态处理与分页相关的页码显示:ReactJS

    我有一些分页逻辑工作得很好 唯一的问题是我只能让它显示并固定数量的页面可供选择 现在我已经把它放到了 5 页 但我希望它能够根据总记录动态更改 假设我有 100 条记录 每页限制为 10 条 将有 10 页 现在我只能让它以这种方式显示 第
  • 按下回车键时不刷新页面

    我遇到了一些问题 只要表单中有输入 回车键就会触发页面刷新 下面的代码 如果按下回车并且文本区域 input 中没有输入任何文本 则不会刷新页面 但是如果按下回车并且 input中有输入或者光标位于文本区域 我不确定是什么触发了它 因为 s
  • React autoFocus 将光标设置为输入值的开头

    我有一个受控输入 最初显示一个值 我已将该输入设置为自动聚焦 但当我希望它出现在末尾时 光标出现在输入的开头 我知道这可能是因为自动对焦是在值之前添加的 但我不能 100 确定 在输入字段末尾完成光标初始化的最佳方法是什么 var Test
  • JavaScript 继承;调用和原型

    要在Javascript中实现继承 通常需要执行以下两个步骤 假设我有一个基类 Animal var Animal function name this name name 我现在想从中派生一个子类 Dog 所以我想说 var Dog fu
  • 如何通过单击链接来更改 div 的内容?

    这是我的网页的 修改后的 jsfiddle 它还有很多 而且定位是正确的 与此相反 http jsfiddle net ry0tec3p 1 http jsfiddle net ry0tec3p 1 a href class btn1 st
  • JavaScript 中的 Promise 有什么意义?

    一个承诺是一个 可能现在可用 或将来可用 或永远不可用的值 来源 MDN 假设我有一个想要处理图片的应用程序 图片已加载 例如在算法在后台使用它之后 或某种其他类型的延迟 现在我想检查一下图片是否可以在future 通过使用承诺 而不是回调
  • mongodb 聚合 - 累积字段的不同组值

    如果我有Player表格文件 name String score Int 我有Group文档 其中组代表玩家列表 groupName String players ObjectID 玩家可以属于多个组 我想做一个聚合Player文档 按以下
  • LeafleteachLayer函数不会迭代所有Layer

    使用 GeoJSON 数据数组创建一些标记 getJSON GetLocationsServlet function data L geoJSON data onEachFeature onEachFeature addTo mymap G
  • 聆听 Angular 2 中的元素可见性

    我正在为我的网络应用程序使用 Bootstrap 和 Angular 2 v4 我想监听指令中的元素以了解可见性变化 我的元素有一个可以隐藏其子元素的父元素hidden sm up我需要在每次隐藏或显示时触发一个函数 div hidden
  • 使用 Javascript 设置 cookie [重复]

    这个问题在这里已经有答案了 我正在尝试构建我的第一个移动应用程序 它需要连接到我的 mysql 数据库并使用 json 返回数据 这很好 目前我有一个登录系统 一旦确定用户名和密码存在 它就会返回一条成功消息 对于下一步 我想在我的页面上使
  • $resource.query 返回分割字符串(字符数组)而不是字符串

    我正在使用像下面这样的 Angular resource angular module app factory data function resource var Con resource api data update method P
  • 在 iOS 7 Safari 中,如何区分通过边缘滑动与后退/前进按钮的 popstate 事件?

    在 iOS 7 Safari 中 现在有两种后退 前进导航方式 使用底部的传统后退 前进按钮箭头或从屏幕边缘滑动 我正在使用动画在 ajax 应用程序中的页面之间进行转换 但如果用户通过边缘滑动进行导航 我不想触发该转换 因为这本身就是一个
  • 滚动顶部不符合预期

    Note 由于上次忘记奖励而重新开放赏金 A Woff 大师已经给出答案 我想在用户展开某一行时到达该行 这样当最后一个可见行展开时 用户不必向下滚动即可查看内容 I used example tbody on click td green
  • 如何通过索引访问 JSON 对象中的字段

    我知道这不是最好的方法 但我别无选择 我必须通过索引访问 JSONObject 中的项目 访问对象的标准方法是只写this objectName or this objectName 我还找到了一种获取 json 对象内所有字段的方法 fo

随机推荐

  • Swift 中“static var”和“var”的区别

    Swift 中 static var 和 var 的主要区别是什么 有人可以用一个小例子向我解释这种差异吗 static var属于类型本身 而var属于类型的实例 特定类型的特定值 例如 struct Car static var num
  • PropertySource 在 ConditionalOnExpression 评估期间不可用

    我有以下组件类 我想根据属性实例化它 Component componentA PropertySource classpath components properties ConditionalOnExpression component
  • android4.0中按串行顺序执行异步任务

    我已经实现了2个异步任务 我使用的是android4 0 其中一个异步任务连续执行 第二个异步任务根据需要执行 可能多次 例如 class AsynTask1 exetends AsyncTask
  • 在 Scala 中,我如何将事件驱动编程与函数式方法结合起来?

    为了澄清事件驱动的含义 我指的是一种情况 def onTrade 每次特定股票交易时都会调用它 假设我想跟踪每日最高交易价格 对我来说 显而易见的解决方案是 var dailyHigh 0 def onTrade if price gt d
  • 汇编语言中的伪随机生成器

    我需要一个用于课程中分配的汇编程序的伪随机数生成器算法 并且我更喜欢一个简单的算法 但是 我无法使用外部库 什么是好的 简单的汇编伪随机数生成器算法 简单的方法是选择两个大的相对素数 a 和 b 然后继续将随机数乘以 a 并加上 b 使用模
  • 如何根据模式将列表拆分为子集?

    我正在这样做 但感觉这可以用更少的代码来实现 毕竟是Python 从列表开始 我根据字符串前缀将该列表拆分为子集 Splitting a list into subsets expected outcome sub 0 a sub 0 b
  • python中的三重引号

    所以我明白如果我执行以下操作 print Anything I type in here works Multiple LINES woohoo 但是如果下面是我的 python 脚本怎么办 This is my python Script
  • 带有“--enable-shared”标志的奇怪 Python 编译结果

    我正在使用 Debian 附带 Python 2 7 3 尝试从源代码编译 Python 2 7 6 以便与 mod wsgi 和 Apache 一起使用 根据众多答案 显然 在编译 mod wsgi 用法时 您必须使用 enable sh
  • 如何创建对角分割且两半可单击的布局?

    我需要创建一个布局 将屏幕对角线分成两个部分 并以不同的颜色作为背景 像这样的 我怎样才能实现这个目标 这可以按如下方式完成 创建一个FrameLayout 假设 50x50 像素 创建两个ImageViews 在FrameLayout并将
  • 从 Azure Active Directory 获取个人资料图片

    我们已将 Azure AD 设置为应用程序中的身份提供商 我们希望在应用程序中显示应来自 Azure AD 的个人资料图片 为了进行测试 我在 Azure AD 中添加了一个 Windows Live Id 帐户 具有个人资料图片 然后我们
  • 将模型中没有的字段添加到 Django REST 框架中的序列化器

    我有一个模型注释 创建时可能会也可能不会创建新用户 因此 我的 API 在创建新评论时需要密码字段 这是我的评论模型 class Comment models Model commenter models ManyToManyField C
  • 如何使用结构体属性设置默认值?

    我想知道如何将 DefaultValue 属性应用于结构属性 您可以注意到 Microsoft 使用表单的大小和许多其他属性来实现这一点 它们的值的类型是 Size Point 等 我想对我的自定义结构做同样的事情 DefaultValue
  • 如何在Python中获取匹配行之后的行

    我是一个业余爱好者 断断续续地使用 Python 一段时间了 抱歉 如果这是一个愚蠢的问题 但我想知道如果输入文件中的格式如下所示 是否有人知道一种简单的方法来获取一堆行 标题 1 Line 1 Line 2 Line 3 标题 2 Lin
  • 创建忽略鼠标和按键事件的 JavaFX 透明窗口

    我想制作一个 JavaFX 应用程序 基本上用一个覆盖整个用户屏幕Canvas对象 所以基本上我可以在用户屏幕上绘制任何内容 制作一个覆盖整个屏幕的窗口很简单 通过本教程可以使其基本上透明 https assylias wordpress
  • 用Java计算两个日期之间的天数

    我想要一个计算两个日期之间的天数的 Java 程序 输入第一个日期 德语表示法 带空格 dd mm yyyy 输入第二个日期 该程序应计算两个日期之间的天数 如何包含闰年和夏令时 My code import java util Calen
  • 响应式 UI 提示

    当我想创建响应式用户界面时 我只想要一些提示 我知道如何使用 Dispatcher Task BackgroundWorker Threads 我正在寻找更多高级提示 例如绑定提示 当我的 UI 上有 50 多个控件需要更新时 Priori
  • 缺少 python bz2 模块

    我已经安装在我的主目录中 spatel dev1 home spatel python 2 7 3 bin python V Python 2 7 3 我正在尝试运行一个需要 python 2 7 x 版本的脚本 但出现丢失 bz2 错误
  • 可以通过 Apache 下载文件吗?

    Path var lib foo txt 是否可以配置 Apache 以便有一些 HTTP URL 可以启动该文件的下载以及如何配置 Without htaccess file 那么那个 URL 会是什么 localhost var lib
  • Google 云存储 CNAME URL 重定向

    我在 Google Cloud 存储上有一个公共存储桶 wordgamesswf 可以通过网址访问对象http commondatastorage googleapis com wordgamesswf linguistics 我需要托管我
  • 原型还是内联,有什么区别?

    我刚刚学习 Javascript 我想知道是否使用原型声明 如下所示 function TSomeObj this name my object TSomeObj prototype showname function alert this