即使作为一个有点经验丰富的JS开发人员,我发现自己也常常对浅物和副物的副本感到惊讶.
当通过引用复制JavaScript值时,是否有任何经验法则,而不是主要对象类型的值?例如,我知道字符串值总是按值而不是引用复制.
我一直在使用Javascript Revealing Module模式,我喜欢它在公共接口和内部之间的明确分离.但是我一直遇到一种情况,这让我想知道我的整体使用模式是否正确,或者我是否应该使用该模式的某些变体.
问题是,当某些内容传递到模块的init函数并私有存储以供内部使用时,还需要在Knockout绑定表达式或其他模块中公开公开.模块的return语句立即执行,稍后调用init函数,通常会传递一些动态参数,如Ajax URL或Razor视图中脚本块中呈现的原始JSON.因为模块的return语句只返回私有变量的副本而不是引用,所以我在init函数中设置的私有变量不能改变已经返回的内容.
var productsModule = function() {
var urls;
var init = function(ajaxUrls) {
urls = ajaxUrls;
};
return {
init: init,
urls: urls,
getUrls: function() { return urls; }
};
}();
var customersModule = function() {
var doSomethingWithProductsModule = function() {
alert(productsModule.urls); // undefined
alert(productsModule.getUrls()); // object
} ;
return {
doSomethingWithProductsModule: doSomethingWithProductsModule
};
}();
var urls = {
getProduct: '/Product/'
};
productsModule.init(urls);
customersModule.doSomethingWithProductsModule();
Run Code Online (Sandbox Code Playgroud)
我的解决方法是在函数中包装诸如"urls"之类的对象,然后通过productsModule.getUrls()访问它们.然而,这变得非常混乱,特别是如果变量是一个Knockout observable,它本身就是一个函数,因此为了评估它我需要使用像productModule.getMyObservable()()这样的双括号.
是否有更好的方法来使用至少接近显示模块模式的东西来获取最新的内部值?
关于Javascript的快速问题我无法找到明确简洁的答案.
我正在构建一个远远超过我之前所做的任何应用程序的应用程序,并涉及实例化多个类.然后将这些对象传递到一个处理类,该类检查用户输入,绘制到画布并更新已传递的对象.
我想知道,JavaScript如何处理将对象传递给函数?我传递了对象的副本,还是我传递了对象的引用?
因此,如果我的控制器类改变了其中一个对象变量,那么它是在任何地方改变的,还是只在该控制器看到的对象中改变了?
对于这样一个简单的,可能很容易测试的问题,我很抱歉,但由于错误堆积,我甚至不确定我是否正确地制作了一个课程.
我需要一些帮助来理解NodeJ.我显然缺少一些基本的东西.我有一个类似于以下的模块,使用基本的显示模块模式...
var someArray = [];
var publicApi = {
someArray: someArray,
someFunction: someFunction
};
function someFunction() {
someArray = ['blue', 'green'];
}
module.exports = publicApi;
Run Code Online (Sandbox Code Playgroud)
当我使用这个模块时,someArray在我调用someFunction时没有改变...
var myModule = require('myModule');
myModule.someFunction();
var test = myModule.someArray;
// test is always an empty array
Run Code Online (Sandbox Code Playgroud)
请帮我理解原因.我意识到我可以使用构造函数来使用它,但我想填补我的知识,为什么以上不起作用.
更新:
我可以通过以下对模块的修改来实现这一点......
var theModule = {
someArray: [],
someFunction: someFunction
};
function someFunction() {
theModule.someArray = ['blue', 'green'];
}
module.exports = theModule;
Run Code Online (Sandbox Code Playgroud)
但我仍然想明白为什么第一个模块中的代码不起作用.我正在处理的模块很好,作为一个单例,所以我很想看看在模块中有变量的最佳实践是什么,可以通过该模块中的函数进行更改,并且可以在该模块之外公开访问.
我编写了一个 for 循环,由于某种原因拒绝修改全局变量。相反,它似乎创建了一个临时修改的局部变量。我的代码的精简版本如下。
var clubsArray = [obj, obj, obj];
//each obj contains a property of "goalsFor" which holds an integer
var madridTotalGoals = 0;
var barcaTotalGoals = 0;
function findTotalGoals(clubsArray, totalGoals) {
for(var i = 0; i < clubsArray.length; i++) {
totalGoals += clubsArray[i].goalsFor;
}
}
findTotalGoals(clubsArray, barcaTotalGoals);
// this loops properly and does the math, but it never changes the value of barcaTotalGoals
Run Code Online (Sandbox Code Playgroud)
在完整的代码中,有许多数组保存“club”对象;每个都包含一个属性键“goalsFor”,它保存一个整数作为值。还有许多已全局声明的“totalGoals”变量(此处指定了两个)。
有谁知道为什么全局变量(例如 barcaTotalGoals)在通过此函数时没有被修改?当我控制台记录此循环的每个步骤时,数学正在进行,但结果没有被存储。如果之前有人问过这个问题,我深表歉意,但我已经彻底搜索过。
如果我有这样的对象:
obj = {a:{aa:1}, b:2};
Run Code Online (Sandbox Code Playgroud)
我想创建一个快捷变量(指向obj.a.aa的指针)x,如下所示:
x = obj.a.aa;
Run Code Online (Sandbox Code Playgroud)
然后我想使用x将值3分配给obj.a.aa,如下所示:
x = 3; // I would like for obj.a.aa to now equal 3
console.log(obj.a.aa); // 1 (I want 3)
Run Code Online (Sandbox Code Playgroud)
如何将x设置为导致值3进入obj.a.aa?
我知道obj.a.aa是一个原始的,但是如何定义一个指向它的变量,然后我可以使用它来为属性赋值?
我对async.auto中从一个任务到另一个任务的结果逻辑感到困惑.例如,在下面的代码逻辑中,我向模型中添加了一些数据task1,这些数据最初是从模型的输出initialtask和finalTask添加的数据task1中反映出来的results.initialTask1.同样添加的数据task2反映在results.initialTask1中finalTask.
综上所有的results.initialTask1,results.task1[0],results.task2[0],results.task3[0]在相同的finalTask.这是逻辑async.auto吗?或者它是否像C++中的指针引用那样导致模型的任何变化task1,它也反映在模型中initialTask?
async.auto({
initialTask: function(callback) {
//Do some operations
callback(null, name, initialModels);
},
task1: ['initialTask', function(callback, results) {
var models = results.initialTask[1];
//Add some more data to models
callback(null, models);
}],
task2: ['initialTask', function(callback, results) {
var models = results.initialTask[1];
//Add some more data to …Run Code Online (Sandbox Code Playgroud) 当我创建一个react类的几个实例时(通过在同一个类上使用React.createElement),一些成员变量在实例之间共享(数组和对象是共享的,字符串和布尔值等等).
对我来说,这感觉太可怕,可怕和错误.这是一个错误还是有另一种方法可以做我想做的事情?
请看一下:http: //jsbin.com/kanayiguxu/1/edit?html,js,console,output
据我了解,Javascript通过引用传递对象,数组也是一个对象,但是当我创建一个整数数组然后将它传递给一个函数时,如下代码:
function testFunc(outTestArray) {
var aiTemp = [1,2,3,4];
/*Using slice(0) to clone array */
outTestArray = aiTemp.slice(0);
}
var aiTest = Array.apply(null, Array(4)).map(Number.prototype.valueOf, 0);
testFunc(aiTest);
console.log(aiTest.toString()); // aiTest still [0,0,0,0]
Run Code Online (Sandbox Code Playgroud)
我也知道 slice(0) 函数只返回数组的浅拷贝,但如果数组只是一个整数数组。所以我的问题是为什么aiTest的数据没有被修改?
我在Vuex getter中发现了JSON的一些奇怪行为:看来这是导致按引用传递类型的问题的原因。对于上下文-我正在开发一个音乐应用程序,它将具有多个“场景”,每个场景都包含“曲目”的集合(类似于Ableton Live)。
这是我的吸气剂:
newTrack: state => {
let newTrack = JSON.parse(JSON.stringify(state.newTrackDefaults))
return newTrack
},
Run Code Online (Sandbox Code Playgroud)
这是它所指的对象:
newTrackDefaults: {
tune: [],
// and other properties
},
Run Code Online (Sandbox Code Playgroud)
然后由一个动作调用它:
setUpNewScene: context => {
let newScene = JSON.parse(JSON.stringify(context.state.newSceneDefaults))
let newTrack = context.getters.newTrack
console.log(newTrack) // this reveals that the problem is from the getter
newScene.tracks.push(newTrack)
context.commit('addNewScene', newScene)
}
Run Code Online (Sandbox Code Playgroud)
因此,此代码的问题是,当我在第一个场景的轨道上添加项目(音高参考),然后添加新场景时,新场景会自动接收与第一个场景相同的轨道。这反映在Vuex状态中(根据DevTool),而不仅仅是渲染。而且,当用户更新第一场景上的轨道时,新场景上的轨道相应地改变。因此,本能地感觉就像是按引用传递类型的错误。
通过各种console.log实验,我发现吸气剂正在返回“填充”轨迹。通过跳过getter并将操作编写为:
setUpNewScene: context => {
let newScene = JSON.parse(JSON.stringify(context.state.newSceneDefaults))
let newTrack = JSON.parse(JSON.stringify(context.state.newTrackDefaults))
console.log(newTrack) // this works fine
newScene.tracks.push(newTrack)
context.commit('addNewScene', …Run Code Online (Sandbox Code Playgroud) javascript ×10
node.js ×2
arrays ×1
asynchronous ×1
class ×1
closures ×1
for-loop ×1
function ×1
knockout.js ×1
reactjs ×1
scope ×1
variables ×1
vue.js ×1