javascript - "JavaScript: The Good Parts"- 实现原型(prototype)方法的方式?

标签 javascript methods prototype

看完这篇文章https://www.toptal.com/javascript/es6-class-chaos-keeps-js-developer-up以及随后的“JavaScript: The Good Parts”,我将致力于成为一名更好的 JavaScript 开发人员。然而,我还有一个问题。我通常实现这样的方法:

function MyClass(){
    this.myData = 43;
    this.getDataFromObject = function(){
        return this.myData;
    }
}

MyClass.prototype.getDataFromPrototype = function(){
    return this.myData;
}

var myObject = new MyClass();
console.log(myObject.getDataFromObject());
console.log(myObject.getDataFromPrototype());

我的假设是整个帖子的基础是 getDataFromObject 更快(在调用期间,而不是在对象创建期间),因为它保存了对原型(prototype)的间接性,但它的内存效率也较低,因为每个对象都有自己的函数对象实例。如果这已经是错误的,请纠正我,您可能可以在这里停止阅读。

其他:文章和书籍都推荐这样的风格:
function secretFactory() {
    const secret = "Favor composition over inheritance [...]!"
    const spillTheBeans = () => console.log(secret)

    return {
        spillTheBeans
    }
}

const leaker = secretFactory()
leaker.spillTheBeans()

(引用文章,这本书还没有 ES6,但想法是相似的)

我的问题是这样的:
const leaker1 = secretFactory()
const leaker2 = secretFactory()

console.log(leaker1.spillTheBeans === leaker2.spillTheBeans) // false

我不是最想避免每个对象都获得每个方法的自己的实例吗?这里可能无关紧要,但是如果spillTheBeans 更复杂并且我创建了无数个对象,每个对象都有12000 和其他方法?

如果是这样,“好零件”解决方案是什么?我的假设是:
const spillStaticBeans = () => console.log("Tabs rule!")
const spillInstanceBeans = (beans) => console.log(beans)

function secretFactory() {
    const secret = "Favor composition over inheritance [...]!"

    return{
        spillStaticBeans,
        spillInstanceBeans: () => spillInstanceBeans(secret)
    }
}

const leaker1 = secretFactory()
const leaker2 = secretFactory()

leaker1.spillStaticBeans()
leaker2.spillInstanceBeans()

console.log(leaker1.spillStaticBeans === leaker2.spillStaticBeans) // true
console.log(leaker1.spillInstanceBeans === leaker2.spillInstanceBeans) // false

splashInstanceBeans 方法仍然不同,因为每个实例都需要自己的闭包,但至少它们只是包装了对包含所有代价的同一个函数对象的引用。

但是现在我必须将每个方法名称写两到三遍。更糟糕的是,我用公共(public)的spillStaticBeans 和spillInstanceBeans 函数弄乱了命名空间。为了减轻后者,我可以编写一个元工厂模块:
const secretFactory = (function(){

    const spillStaticBeans = () => console.log("Tabs rule!")
    const spillInstanceBeans = (beans) => console.log(beans)

    return function() {
        const secret = "Favor composition over inheritance [...]!"

        return{
            spillStaticBeans,
            spillInstanceBeans: () => spillInstanceBeans(secret)
        }
    }

}())

这可以像以前一样使用,但现在方法隐藏在闭包中。然而,它变得有点困惑。使用 ES6 模块,我也可以将它们留在模块范围内而不是导出它们。但这是要走的路吗?

还是我总体上错了,JavaScript 的内部函数表示处理了所有这些并且实际上没有问题?

最佳答案

My assumption that underlies this whole post is that getDataFromObject is faster to call than getDataFromPrototype because it saves an indirection to the prototype



不,引擎非常擅长优化原型(prototype)间接性。 instance.getDataFromPrototype对于同一类的实例,总是解析为相同的方法,引擎可以利用这一点。见 this article详情。

Do I not mostly want to avoid that every object gets an own instance of every method? It might be insignificant here



是的。在大多数情况下,它实际上是微不足道的。因此,使用您喜欢的任何样式使用方法编写您的对象。仅当您实际测量性能瓶颈时,才重新考虑创建许多实例的情况。

Using ES6 modules, I could also leave them in module scope and just not export them. But is this the way to go?



是的,这是一个明智的解决方案。但是,没有充分的理由提取 spillInstanceBeans到静态范围,只需将其保留在原处 - 您必须在 secret 上创建一个闭包反正。

关于javascript - "JavaScript: The Good Parts"- 实现原型(prototype)方法的方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61068112/

相关文章:

javascript - 如果字符串为空,如何隐藏元素或 div?

Javascript原型(prototype)和访问 'this'的父对象

javascript - 单击鼠标后动画不会停止(JavaScript)

C#:分析 "unsafe"方法调用

java - 为什么 Java 编译器不能从另一个文件中找到类?

java - 反转数组的方法会导致 StackOverflowError

javascript - JS继承原型(prototype)时如何传递参数?

javascript - 将相同函数分配给 JavaScript 中的多个变量时的性能问题

javascript - 如何从标记函数中调用原生 es6 模板字符串替换?

javascript - 您可以使用 python 中的映射或其他高阶函数来跟踪索引吗?