在对象中引用Javascript对象的正确方式

Right way of referencing Javascript Objects inside Objects

本文关键字:对象 方式 Javascript 引用      更新时间:2023-09-26

我是JavaScript的新手,我对我的应用程序中使用的以下遗留淘汰和JS代码不太确定:

file1.js:

var FbPicturesObj = {
    fbPicturesVM: new FbPicturesVM(),
    initialize: function () {
        ko.applyBindings(FbPicturesObj.fbPicturesVM, $("#fb-albums")[0]);
        ko.applyBindings(FbPicturesObj.fbPicturesVM, $("#fb-album-photos")[0]);
    },
    Reset: function Reset() {
        FbPicturesObj.fbPicturesVM.albums([]);
        FbPicturesObj.fbPicturesVM.photos([]);
    }
}

file2.js:

function FbPicturesVM() { 
...... some code ....
 }

我的问题是:

  1. 是否每次调用FbPicturesObj.fbPicturesVM都会在内存中创建一个fbPicturesVM的新实例
  2. ko.applyBindings调用是否正确写入?(在代码优化方面)

非常感谢。

File1.js包含JavaScript对象的定义,更确切地说是一个";文字对象创建";。

在它内部,每个propertyName: value对声明一个初始化一个新属性,这样在创建对象时代码只运行一次。例如fbPicturesVM: new FbPicturesVM()

JavaScript对象的属性可以是函数,例如:initialize: function () {...},。在这种情况下,无论何时运行FbPicturesObj .initialize,都会运行此函数。

ko.applyBindings的调用是正确的。此方法需要viewmodel对象和可选的DOM元素作为第二个参数。jQuery表达式(不完全是)所选DOM元素的数组,因此此$("#fb-album-photos")[0]根据ko.applyBindings的需要提取jQuery表达式的第一个DOM元素。

注意:正如您所怀疑的,定义模型的方式至少不是最好的。您可以使用显示模块模式,这使事情变得更加容易

显示模块模式

简而言之:

var vm = (function() { // declare a function
   // create variables and functions
   var name = ko.observable();
   var age = ko.observable();
   var _privateVar = 'Yuhu'; // won't be revealed
   var incAge = function() {
      age = age + 1;
   };
   // reveal only what you want, by returning it in an object
   return {
     name: name,
     age: age,
     incAge: incAge
     // note that _privateVar is not exposed, but could be
   }
})(); // This invokes the function, so that it return the model

注意模式"立即调用函数表达式"(IIFE)。

var value = (function() {/*return something*/})(); 

这个模式定义了一个匿名函数,它返回一些东西。最后的()运行它,从而返回值,并存储在value中;

我推荐这种模式,因为它非常容易使用,而且很少出错。经典的原型继承、构造函数和诸如此类的东西都很难处理。

您可以在视图模型工厂(类似于构造函数,但实际上不是js构造函数)中轻松地转换它,方法是删除调用-末尾的()-并存储函数定义,这样您就可以重复调用它。

var factory = function() {/*return something*/}; 
var vm1 = factory();
var vm2 = factory();

FbPicturesVM的构造函数仅在实例化FbPicturesObj对象时调用(在您的示例中,这将仅在脚本包含在页面中时调用)。因此,就内存而言,您只有一个实例,然后将引用传递给它(JS主要通过引用传递对象)。

我不太了解敲除,但语法上并没有错,传递一个对象和一个元素听起来对绑定代码来说是正确的。

这个问题应该分开,因为第一个问题与Knockout无关,更多的是关于对象文字如何与实例化对象相关联。

因此,对于问题1,答案是"否",因为FbPicturesObj保存实例化的属性FbPictures.fbPicturesVM

考虑以下内容:

var Person = function(name) {
	this.name = name
}
Person.prototype.sayName = function() {
	return this.name
}
var people = {
	fred : new Person('fred')
}
console.log(people.fred.sayName()); // returns 'Fred'
var people = {
	fred : new Person('jane')
}
console.log(people.fred.sayName()) // returns 'jane' and not 'fred'
var people = {
	fred : new Person('fred'),
  jane : new Person('jane')
}
console.log(people.fred.sayName()) // returns 'fred'
console.log(people.jane.sayName()) // returns 'jane'

在这种情况下,每次调用"person.fred"都将始终引用同一个实例,因为它已保存到people对象中。