在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吗?它是如何使用的,我该如何使用它。使用这种方式而不是使用我描述的方法有什么好处?你为什么要原型而不是第一次正确地上课?
答案 0 :(得分: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]
答案 1 :(得分: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 不是传统的面向对象语言,所以没有类,你不应该考虑类。但原型非常强大,我认为它比类更强大。网上有很多关于如何使用原型复制类但不是相反的例子。
答案 2 :(得分: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);
}
};
答案 3 :(得分:0)
var object = new function () {
//
}
var myObject = new object();