为什么特权方法和公共方法有区别?
为什么我甚至不打扰公共方法,没有特权 方法更自然?他们觉得更直观,因为他们允许访问 私有方法和变量,如java。
这个背后是否有一个特定的原因,或者这是一个错误
spec (在那里领先一点!)或者我错过了什么?
这是演示的代码:
var Foo = function(){
var privateVar = "i am private";
function privateFunc(){
console.log(privateVar);
}
this.privilegedFunc = function(){
privateFunc(); // can access
}
};
Foo.prototype.publicFunc = function(){
privateFunc(); // cannot access
};
var foo = new Foo();
foo.privilegedFunc(); // prints "i am private"
foo.publicFunc(); // Uncaught ReferenceError: privateFunc is not defined
答案 0 :(得分:3)
它就像任何OOP语言一样(尽管没有可见性关键字),如果你需要在实例之外调用一个方法,public,else,private。
未绑定到this
的函数无法在范围外访问,因为它们是在构造函数的范围内定义和声明的。
根据您的最新评论,有许多原因和场景,您必须公开对象功能才能被其他对象使用,例如
根据你在这个答案中的评论,让我们看看原型方法的一些优点。
通过使用原型,您可以更改方法,并且更改将反映到共享相同原型的所有实例,没有原型,每个实例将拥有它自己的给定方法版本,因此您将不得不一个一个地改变它们。
另一个优点是性能,原型中声明的函数/方法只创建一次,而没有原型,每次使用new
关键字从构造函数实例化时,构造函数内的所有函数必须创建范围。
答案 1 :(得分:2)
重要的是要注意,“特权”和“公共”方法之间的规范没有区别(实际上我认为规范根本不使用这些术语 - 道格拉斯·克罗克福德),它们受到确切的控制相同的规则,其中最基本的是功能范围。
注意 :我会在答案中遵循您的术语,但实际上我建议您不要这样做:更多时候您会发现人们调用您的特权方法public,以及您的公共方法原型方法。
在您的示例中,this.privilegedFunc
可以访问私有变量privateFunc
,因为它们是在同一范围内定义的 - 即Foo
构造函数的范围。 privilegedFunc
即使从“外部”调用,也可以通过所谓的语言闭包机制来使用它对privateFunc
的引用。
直接回答您的问题:
为什么特权方法和公共方法之间有区别?
没有根本的区别。您在不同的范围中定义了两个函数,因此,它们可以引用不同的变量。
为什么我甚至不愿意使用公共方法,特权方法不是更自然吗?
自然是一个非常主观的术语。但是,如果您不希望直接公开字段,则需要使用特权函数从外部操作它们。
他们感觉更直观,因为他们允许访问私有方法和变量,如java。
这种直觉仅仅基于熟悉度:)难怪当你尝试使用Javascript作为Java时,在两种语言中工作方式不同的部分似乎最不直观。这并不意味着您应该尝试模仿您在另一个中使用的样式,一些解决方案更适合Javascript,一些更适合Java。
这背后是否存在特定原因,或者这是规范中的错误还是我遗漏了什么?
(规范中的这样一个基本错误?!上帝没有。)我不确定你对“this”的意思,但可见性的差异由功能范围解释,见上文。
在什么情况下你会使用公共方法而不是特权方法?
例如,如果您不需要通过闭包公开私有字段。另一个值得注意的区别是原型上的函数将在实例之间共享(即实际上是相同的函数实例),而私有和特权方法对于实例是唯一的,这会对内存占用产生影响。
答案 2 :(得分:1)
您所谓的“特权”方法不是语言语法的一部分。相反,它是一种设计模式。这是有可能的,因为javascript实现了闭包(即使在外部函数返回之后,函数也能够访问外部函数的范围)。
有一种理论认为,所有实现闭包的语言(甚至只是第一类函数)都可以实现一个对象系统。在向语言添加OO时,有几种函数式语言采用了这种方法:OO功能不是语言语法的一部分,而是可以使用(甚至自己编写)的库。其中一个主要的例子是Lisp中的CLOS(Common Lisp Object System)。它是一个库,可以为语言添加OO功能,而无需修改语言语法。
正如您所发现的,使用闭包来访问局部变量可以很好地模拟私有变量和公共方法的“感觉”。这是闭包的一个特性 - 您可以创建自己的OO系统而无需OO功能。
javascript中的OO系统被添加,因为OO是一个大问题。不可否认,如果Brendan Eich没有在javascript中添加OO,我们可以使用纯javascript从头开始进化(或几个)OO系统。实际上,在21世纪初,人们对javascript中的原型对象系统不满意,并开发了自己的OO系统来模仿他们习惯的东西。
在javascript中,OO系统没有私有方法或变量的概念。这是故意的。其他几种语言也有这样一种理念,即私人成员是一个“错误”。隐私是不良做法的想法源于多年使用库的经验,这些库创建了您需要访问私有的功能。对于鼓励开源或分发代码不太大的语言。您始终可以修改库代码以导出所需内容。但对于鼓励将库分发为已编译二进制文件的语言而言,这是一个很大的问题。在创建javascript时,大多数OO语言都具有允许您将库分发为已编译二进制文件的功能。因此,对隐私概念的反对很小。
那么......你何时会使用闭包来模拟私有变量?当你真的需要像私人变量这样的东西时使用它。
答案 3 :(得分:0)
为什么特权方法和公共方法之间有区别?
我假设你读过Douglas Crockford网站(this page)。这是我从未被其他作者看到的区别。我没有做出这种区分,但我知道该函数可以访问构造函数闭包。
为什么我甚至不愿意使用公共方法,没有特权方法更自然?他们感觉更直观,因为他们允许访问私有方法和变量,如java。
它们与public
方法的含义不同。
A)它们由构造函数定义,因此,它们可以访问构造函数作用域。这是他们的特权。
B)它们的原型并没有共享。
A 表示每次调用构造函数时都会实例化该函数。当您使用原型时,它只是链接。
B 意味着它们本质上是不同的功能。
obj1.privileged !== obj2.privileged
这背后是否存在特定原因,或者这是规范中的错误还是我遗漏了什么?
我看到的地方没有错误。它只是一种语言功能。
在什么情况下你会使用公共方法而不是特权方法?
如果您不需要访问构造函数中的任何闭包,并希望利用原型链。
答案 4 :(得分:0)
不确定语义和命名约定,但就模式而言,这是我在大多数情况下如何解决这个问题:
Object.keys()
相同),但这不会在原型上声明,而是直接在类型上声明。答案 5 :(得分:0)
为什么特权方法和公共方法之间有区别?
这是语言设计的结果,而不是驱动因素。实际上你可以做得很好,而不必担心我认为这个术语的区别。
为什么我要打扰公共方法,没有特权 方法更自然?他们觉得更直观,因为他们允许访问 私有方法和变量,如java。
这背后是否存在具体原因,或者这是规范中的错误>或者我错过了什么?
在什么情况下你会使用公共方法而不是特权方法?
在某些情况下,您可能会想到自己想到的公共方法:
答案 6 :(得分:0)
你正在以错误的方式思考这个问题。您应该考虑范围而不是访问级别(公共/私有/受保护)Javascript不是传统的面向对象编程语言。
在您的示例中,“privateMethod”简单地限定为“Foo”函数,因此无法在函数外部访问。您的“privilegedFunction”附加到“this”,它在javascript中是“Foo”函数的上下文。您可以从示例中显示的Foo“实例”访问它,因为它具有作用域,并且与访问级别无关。