2

在 JavaScript 中有很多方法可以做同样的事情。然而,我已经掌握了一些方法,坦率地说,有些方法我不明白。谁能帮我澄清一些事情?(我首先在 PHP 中学习了 OOP。)

所以可以像这样制作一个类:

var object = new class(constructparams) {
    var private_members; // Can be accessed from within the code inside this definition only.
    this.public_members; // Can be accessed from everywhere.

    var private_functions = function() {}
    this.public_functions = function() {}
}

object.prototype.semi_public_members = function() {
    // Will be public, but can only access public members and methods.
    // E. g. private_members; is not available here.
}

到目前为止,这一切都正确吗?

然后有人喜欢自执行匿名函数的方法来创建命名空间。当你在上面做同样的事情时,这有什么意义,提供一个命名空间?

最后你有我不明白的对象文字符号。

var object = { // Something strange in here }

里面发生了什么?是 JSON 吗?它是如何使用的,我该如何使用它。使用这种方式而不是使用我描述的方法有什么好处?为什么你要原型而不是第一次正确地制作课程?

4

4 回答 4

5

通过示例解释构造对象中不同事物的行为:

// Defined as a variable from an anonymous function
// so that there is scope closure over variables
// shared across all instances and the prototype.
// If this isn't important, you don't need to close
// scope around it, so define directly
var ConstructedObject = (function constructorCreator () {
    // Define any variables/methods to be shared across
    // all instances but not polluting the namespace
    var sharedVariable = 'foo';

    // Next the actual constructor
    function ConstructedObject () {
        // Variables here are normally used to help
        // each instance and will be kept in memory as
        // long as the instance exists
        var instanceVariable = 'bar';
        // instance-specific properties get defined
        // using the "this" keyword, these are the
        // properties expected to be changed across
        // each different instance
        this.instanceProperty = true;
        this.instanceMethod = function () { return instanceVariable; };
        this.changeInstanceVar = function () { instanceVariable = 'foo'; };
            // you do have access to the shared
            // variables here if you need them.
    }
    // After the constructor, you set up the
    // prototype, if any. This is an object of shared
    // properties and methods to be inherited by every
    // instance made by the constructor, and it also
    // inherits the prototype's prototype, too.
    // Lets use a literal object for simplicity.
    ConstructedObject.prototype = {
        // Accessing the instance to which a method
        // applies is done using the "this" keyword,
        // similar to in the constructor
        sharedMethod : function () { return [sharedVariable, this.instanceMethod(),this.instanceProperty]; },
        changeSharedVar : function () { sharedVariable = 'bar'; }
        // properties may also be defined
    };
    // Finally, the constructor is returned so it
    // can be kept alive outside of the anonymous
    // function used to create it
    return ConstructedObject;
// and the anonymous function is called to execute
// what we've done so far
})();

执行上述代码后,您将拥有一个构造函数,该构造函数创建具有实例特定变量和共享变量的对象。现在让我们通过创建两个实例并在一些更改前后比较它们来看看它们的行为。

// First create the two instances
var myObjA = new ConstructedObject(),
    myObjB = new ConstructedObject();
// Now compare them, the sharedMethod method we
// used in the prototype offers an easy way to
// do this
console.log( myObjA.sharedMethod(), myObjB.sharedMethod() );
// ["foo", "bar", true] ["foo", "bar", true]
// Next lets change the different variables in
// myObjB so we can see what happens, again the
// change* methods defined before let us do this
// easily
myObjB.changeInstanceVar();
myObjB.changeSharedVar();
// For completeness, lets also change the property
// on myObjB.
myObjB.instanceProperty = false;
// Now when we compare them again, we see that our
// changes to the myObjB instance have only changed
// the shared variables of myObjA
console.log( myObjA.sharedMethod(), myObjB.sharedMethod() );
// ["bar", "bar", true] ["bar", "foo", false]

这是两个记录的语句一起,以便于查看

//     myObjA               myObjB
["foo", "bar", true] ["foo", "bar", true]
["bar", "bar", true] ["bar", "foo", false]
于 2012-11-03T23:31:06.430 回答
1

我认为有些概念似乎丢失了,但我会尽可能多地回答。

所以可以像这样制作一个课程......到目前为止这一切都正确吗?

它很接近,但并不完全正确。您不需要new创建构造函数,仅在创建“类”的新实例时才需要它。

function Klass() { ... } // capitalized name as convention for constructors
var myKlass = new Klass(); //<-- Need "new" here

公共方法可以附加到实例或原型。当您将它附加到原型时,该方法将在所有实例之间共享,从而节省一些内存。

Klass.prototype = {
  publicSharedMethod: function() {
    var self = this;
  }
}

然后有人喜欢自动执行的匿名函数……那有什么意义……

模块模式(或自执行功能)方法有点不同,因为您通常不会处理原型,尽管您可以。它只是一个返回带有属性和方法的文字对象的函数,但是当您不需要该对象的实例时,我主要将它用于单例:

var Singleton = (function() {
  var private = 'foo';
  var public = 'baz';
  var publicMethod = function() { ... }
  // Expose public methods and properties
  return {
    public: public
    publicMethod: publicMethod
  }
}());

最后你有我不明白的对象文字符号。

这只是 JavaScript 中的一个常规对象,类似于 PHP 所称的“关联数组”。文字对象语法是 JSON 的基础,但 JSON 在格式方面有更多限制;JavaScript 更宽容,例如,您可以使用不带引号的属性和方法。

为什么你要原型而不是第一次正确地制作课程?

这里的重点是要理解 JavaScript不是传统的面向对象语言,所以没有类,你不应该考虑类。但是原型非常强大,我会说比类更强大。网上有很多关于如何使用原型复制类的示例,但反之则不然。

于 2012-11-03T22:21:03.997 回答
0

不,这是不正确的。构造函数应该与对象的创建分开:

function myClass(constructparam1) {
  this.public_member = constructparam1; // Can be accessed from everywhere.
}

这些方法应该在构造函数的原型中,而不是实例中:

myClass.prototype.semi_public_members = function() {
  // Will be public
}

使用关键字调用构造函数new来创建实例:

var obj = new myClass(1337);

构造函数内部的局部变量只能在该函数内部访问。如果你的类中没有局部变量,你需要一个围绕它的函数来创建一个闭包,以便原型中的方法可以访问变量:

var myClass = (function(){

  var local_variable;

  function constructor(constructparam1) {
    this.public_member = constructparam1; // Can be accessed from everywhere.
  }

  constructor.prototype.semi_public_members = function() {
    // Will be public
    alert(local_variable); // can access private variables
  }

  return constructor;
})();

对象文字只是一次性创建对象的一种简单但有限的方法。它们没有原型,因此如果您希望它们具有方法,则必须将它们分配给属性:

var obj = {

  public_member: 1337,

  semi_public_members: function(){
    alert(this.public_member);
  }

};
于 2012-11-03T22:12:11.020 回答
0
var object = new function () {
    //
}

var myObject = new object();
于 2012-11-03T22:13:21.527 回答