Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/432.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在原型中使用闭包使方法私有_Javascript_Closures_Prototype Programming - Fatal编程技术网

Javascript 在原型中使用闭包使方法私有

Javascript 在原型中使用闭包使方法私有,javascript,closures,prototype-programming,Javascript,Closures,Prototype Programming,我在我们的项目中使用prototype 1.4,我用这种方式创建类: 1) 举止1 但是,在上面的代码中,可以在外部调用Person“\u check”方法,这不是我所期望的 在我的《感谢T.J.Crowder》一书中,他告诉我一个让方法完全私有化的解决方案: 2) 举止2 现在,“检查”不能暴露在外面 但我现在感到困惑的是,这种方式会导致性能问题还是最好的做法 因为我们创建类(蓝图)的原因之一是为了减少可以在任何地方多次重用的重复代码 现在看看“举止1”: 我们创建一个类Person,然后将所

我在我们的项目中使用prototype 1.4,我用这种方式创建类:

1) 举止1

但是,在上面的代码中,可以在外部调用Person“\u check”方法,这不是我所期望的

在我的《感谢T.J.Crowder》一书中,他告诉我一个让方法完全私有化的解决方案:

2) 举止2

现在,“检查”不能暴露在外面

但我现在感到困惑的是,这种方式会导致性能问题还是最好的做法

因为我们创建类(蓝图)的原因之一是为了减少可以在任何地方多次重用的重复代码

现在看看“举止1”:

我们创建一个类Person,然后将所有实例方法放到类Person的原型对象中。 然后每次我们打电话给

var obj=new Person('xx',21);
对象“obj”将拥有Person.prototype中的方法。“obj”本身不包含任何代码

但在“方式2”中: 每次我们打电话:

var obj=new Person('xx',21);
将创建一个新的蓝图,每次还将创建诸如“\u check”之类的私有方法。 这是浪费记忆吗

注意:也许我错了。但我真的很困惑。有人能给我解释一下吗

将创建一个新的蓝图,每次还将创建诸如“\u check”之类的私有方法。这是浪费记忆吗

你错了。在第二种方法中,您只执行周围函数一次,然后将
person\u real
分配给
person
。代码与第一种方式完全相同(当然除了形式
\u检查
)。考虑第一种方式的变化:

var Person=Class.create();
Person.prototype={
    initialize:function(name,age){
        _check(name,age);
        this.name=name;
        this.age=age;
    },
    say:function(){
        console.log(this.name+','+this.age);
    }
}

function _check(name,age){
    //....the check code here
}
你还会说每次你打电话给新的人时都会创建检查吗?可能不会。这里的区别在于,
\u check
是全局的,可以从任何其他代码访问。通过将此片段放入函数中并立即调用该函数,我们使该函数的
\u check
成为本地函数

方法
initialize
say
可以访问
\u check
,因为它们是闭包

当我们用普通函数调用替换立即函数时,可能对您更有意义:

function getPersonClass(){
    var person_real=Class.create();
    person_real.prototype={
        initialize:function(name,age){
            _check(name,age);
            this.name=name;
            this.age=age;
        },
        say:function(){
            console.log(this.name+','+this.age);
        }
    }

    //some private method
    function _check(name,age){
        //....the check code here
    }
    return person_real;
}

var Person = getPersonClass();

getPersonClass
只调用一次。由于
\u check
是在这个函数中创建的,这意味着它也只创建一次。

你会发现人们在使用Javascript时遇到一些常见的问题

首先是第二个问题,因为它更容易回答。对于原型继承,您只描述两个相关对象之间的差异。如果在对象的原型上创建一个函数,然后对其进行10000个克隆,那么仍然只有一个函数。每个单独的对象将调用该方法,并且由于Javascript中“this”的工作方式,这些函数调用中的“this”将指向单独的对象,尽管函数存在于单个原型中

当然,当您具有唯一的每项属性、每个对象的唯一值时,您就可以解决性能问题(我不太愿意使用术语“实例”,因为与基于类的继承相比,它在原型继承中的含义并不相同)。由于您不再从单个共享函数/数据集中受益,因此您将失去该好处。了解如何最大限度地降低这些低效率是Javascript(以及任何基于原型继承的语言)智能、高效编程的关键部分。有很多不明显的技巧可以让功能和数据以最小的重复共享

第一个问题是Javascript中常见的一类混淆,因为Javascript中几乎无所不能的功能。Javascript中的函数单独完成其他语言中许多不同结构的工作。类似地,Javascript中的对象在其他语言中扮演着许多数据构造的角色。这种集中的职责为这个表带来了许多强大的选项,但使Javascript成为了一种不折不扣的工具:它看起来非常简单,而且非常简单。但这真的很简单,就像扑克真的很简单一样。这只是一小部分移动的片段,但它们的交互方式产生了一个更深层次的元游戏,很快变得令人困惑

最好将Javascript应用程序/脚本/任何东西中的对象/函数/数据理解为一个不断发展的系统,因为这有助于更好地捕获原型继承。也许就像一场橄榄球(美国)比赛,如果不知道有多少次失败、还有多少次超时、你在哪个季度等等,就无法真正捕捉到比赛的当前状态。你必须随着代码移动,而不是像大多数语言一样看它,甚至像php这样的动态语言

在第一个示例中,基本上您所做的就是使用Class.create自动调用
initialize()
函数,并自动处理祖辈构造函数的内容,否则类似于:

var Person = function(){ this.initialize.call(this, arguments) };
Person.prototype = { ... }
没有祖父母的东西。直接在对象上设置的任何属性都将是公共的(除非您使用ES5 defineProperty stuff来专门控制它),因此在名称的开头添加
\uu
不会做任何超出约定的事情。javascript中没有私有或受保护的成员。只有公共属性,因此,如果在对象上定义属性,则该属性是公共的。(再次打折ES5,它确实增加了一些控制,但它并不是真正设计用来填充其他语言中的私有变量,不应该以同样的方式使用或依赖它)

我们必须使用作用域来创建隐私,而不是私有成员。记住Javascript只有函数作用域是很重要的如果您想在对象中拥有私有成员,那么您需要将整个对象包装在更大的范围(函数)中,并有选择地公开
function getPersonClass(){
    var person_real=Class.create();
    person_real.prototype={
        initialize:function(name,age){
            _check(name,age);
            this.name=name;
            this.age=age;
        },
        say:function(){
            console.log(this.name+','+this.age);
        }
    }

    //some private method
    function _check(name,age){
        //....the check code here
    }
    return person_real;
}

var Person = getPersonClass();
var Person = function(){ this.initialize.call(this, arguments) };
Person.prototype = { ... }