Javascript对象定义技术的优缺点

如何解决Javascript对象定义技术的优缺点

| 在Javascript中定义可重用对象的基本方法是什么?我说可重用以排除单例技术,例如直接用对象文字符号声明变量。我在某处看到克罗克福德在他的书中定义了四种这样的方式,但我宁愿不必购买本书以获取这些简短的信息。 这是我熟悉的方法: 使用
this
并用
new
构造(我认为这被称为经典吗?)
function Foo() {
    var private = 3;
    this.add = function(bar) { return private + bar; }
}

var myFoo = new Foo();
使用原型,这是相似的
function Foo() {
    var private = 3;
}
Foo.prototype.add = function(bar) { /* can\'t access private,correct? */ }
不使用
this
new
返回文字
function Foo() {
    var private = 3;
    var add = function(bar) { return private + bar; }
    return {
        add: add
    };
}

var myFoo = Foo();
我可以想到相对较小的变化,这些变化可能不会以任何重要的方式起作用。我想念什么风格?更重要的是,每种技术的优缺点是什么?有值得推荐的人吗?还是优先考虑和一场神圣的战争?     

解决方法

        使用原型。从构造函数返回特定的对象使它们成为非构造函数,而将方法分配给
this
则使继承变得不那么方便。 返回对象文字 优点: 如果一个人忘记了“ 1”,他们仍然会得到物体。 您可以创建真正的私有变量,因为构造函数内部定义的对象的所有方法都共享其作用域。 缺点: 它不是真正的构造函数。在原型中添加内容不会更改返回的对象,即
new
或否
new
new Foo() instanceof Foo
也会导致
false
。 使用
prototype
优点: 您可以使构造函数整洁。 这是用JavaScript进行处理的标准方法,所有内置的构造函数都将其方法放在其原型上。 继承变得更加容易和正确。您可以(并且应该)使用
Object.create(ParentConstructor.prototype)
代替
new ParentConstructor()
,然后从
Constructor
中调用
ParentConstructor
。如果您想覆盖某个方法,则可以在原型上进行。 您可以在对象创建后对其进行“修改”。 您可以扩展您无法访问的构造函数的原型。 缺点: 可能太冗长了,如果您想更改函数的名称,则还必须更改添加到原型中的所有函数。 (或者将原型定义为一个大对象文字,并带有兼容的ѭ18属性描述符。) 它们不共享特定于实例的范围,因此您实际上不能拥有私有变量。 在构造函数中分配给ѭ19 优点: 您可以使用闭包,因此可以使用私有成员变量。 缺点: 没有鸭子打字;您不能使用任何旧对象立即从原型中调用方法。例如,
Array.prototype.slice.call(collectionLikeObject)
。     ,        这主要是偏好问题。没有一种方法可以制作鸡肉面条汤,而且统一的对象也是如此。 我不使用这三个中的任何一个,尽管它们都是出于自己的目的而工作。我使用一个名为Object:deploy的自定义函数,并像这样使用它。
var a = { hey: \'hello\' },b = {}.deploy(a);

console.log(b.hey); // \'hello\'
由于自动点滴,最适合大多数人使用
prototype
function A() {};
A.prototype.hello = \"Hey\";

var a = new A();
console.log(a.hello); // \'Hey\'

A.prototype.hello = \"Hello\";

console.log(a.hello); // \'Hello\'
与普遍看法相反,您可以在in13ѭ中使用私有变量。
function Hello() {};

(function () {
    var greeting = \"Hello\";

    Hello.prototype.greet = function () { return greeting };
}).apply(this);
但是,即使有可能,通常也更好。
function Hello() {};
Hello.prototype.greeting = \"Hello\";
Hello.prototype.greet = function () { return this.greeting };
    ,        好吧,第二种方法(原型)与其他语言(例如Python)中的标准类更相似,因为您有一个公共的“ prototype \”对象,所有实例都可以共享该对象。比较第一种和第二种方法: 在方法1中,每次调用“
new Foo()
\”时,都将创建一个全新的对象并插入所有方法。这不是非常节省时间或空间,因为每个Foo实例将拥有自己的所有方法表。您可以通过创建两个Foo对象并询问
foo1.add == foo2.add
(false)来进行测试。方法3与此非常相似;我不确定方法1和方法3之间的语义差异(如果有)。 在方法2中,您设置了包含所有方法的共享原型对象。如果你问
foo1.add == foo2.add
,那你就成真了。这样更节省空间和时间。它还允许您在创建实例后向原型添加更多方法,并且它们将看到新方法。 如您所说,方法2的问题在于您无法访问私有成员。但是您仍然可以将非私有成员添加到对象本身,并使用原型方法访问那些成员:
function Foo() {
    this.private = 3;
}
Foo.prototype.add = function(bar) { return this.private + bar }
需要注意的是,
foo.private
在外部是可见的。     ,原型没有add对象的每个对象实例的开销。仅这就是为什么我不喜欢其他两种方法的原因。     ,        不要忘记继承。有一天你需要。对于组织继承,最好的方法是结合技术:
function Foo() {
    this.array = [1,2,3];
    this.add = function(bar) { return private + bar; }
}

Foo.prototype.add = function(bar) {  }

var myFoo = new Foo();
在构造函数中设置字段对于避免由子对象修改字段很有用。 将方法设置为原型的速度比每次在构造函数中都要快。     

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-