在嵌套的模块化方法中使用 "this" 并保留名称空间
Using "this" in nested, modular methods and preserving namespaces
我有一个巨大的 JavaScript 整体,并使用基于模块的方法使其更加结构化。
但是,我对如何在嵌套函数中使用“this”关键字而不相互覆盖感到有点迷茫,就像下面的示例可能演示的那样
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = (function () {
const self_localStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought locally");
self_localStore.buyArray = this;
};
return this;
})();
// Buy from online store
this.onlineStore = (function () {
const self_onlineStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought online");
self_onlineStore.buyArray = this;
};
return this;
})();
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
localStore.buy()
方法显然被 onlineStore.buy()
方法覆盖,因为它们都返回到 Fruit() 方法范围,使用相同的名称,最后一个覆盖第一个一.
那么,在不使用具有这些嵌套方法的对象的情况下允许像 onlineStore 和 localStore 这样的“名称空间”的解决方案是什么?
您正在两个函数中创建一个函数变量。但是 this.onlinestore 覆盖了 fruit 的函数变量。这与 setter 函数没有什么不同。想想你可以用两种不同的方法设置一个变量。从上到下,在在线商店功能中,您覆盖 this.buy 方法。
你可以使用下面的例子。
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = () =>{
console.log('local store');
const self_localStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought locally");
self_localStore.buyArray = this;
};
return this;
};
// Buy from online store
this.onlineStore = () => {
console.log('online store')
const self_onlineStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought online");
self_onlineStore.buyArray = this;
};
return this;
};
return this;
}
let fruit = new Fruit();
fruit.localStore().buy("apple"); // -> Bought online, instead of Bought locally
当你写一个IIFE时,this
等于window
或undefined
(取决于你是否使用严格模式):
(function() { console.log(this === window); })() // True
正在为 this
关键字指定调用函数的对象,例如:
const obj = {
fun: function() { console.log(this === obj); }
}
obj.fun(); // True
如果你想创建一些有自己状态的命名空间,我建议你使用这样一个简单的对象:
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = {
buyArray: [],
buy: function (fruit) {
this.buyArray.push(fruit);
console.log("Bought locally:", this.buyArray.join(', '));
}
};
// Buy from online store
this.onlineStore = {
buyArray: [],
buy: function (fruit) {
this.buyArray.push(fruit);
console.log("Bought online:", this.buyArray.join(', '));
}
};
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
fruit.localStore.buy("banana");
fruit.onlineStore.buy("orange");
但是,您可能不喜欢文字对象,因为它们不提供真正的封装(可以从 buy
函数外部访问 buyArray
属性)。
所以您也可以像您最初尝试做的那样将状态封装在 IIFE 中:
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = (function() {
const buyArray = [];
const buy = function (fruit) {
buyArray.push(fruit);
console.log("Bought locally:", buyArray.join(', '));
};
return { buy };
})();
// Buy from online store
this.onlineStore = (function() {
const buyArray = [];
const buy = function (fruit) {
buyArray.push(fruit);
console.log("Bought online:", buyArray.join(', '));
};
return { buy };
})();
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
fruit.localStore.buy("banana");
fruit.onlineStore.buy("orange");
我有一个巨大的 JavaScript 整体,并使用基于模块的方法使其更加结构化。
但是,我对如何在嵌套函数中使用“this”关键字而不相互覆盖感到有点迷茫,就像下面的示例可能演示的那样
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = (function () {
const self_localStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought locally");
self_localStore.buyArray = this;
};
return this;
})();
// Buy from online store
this.onlineStore = (function () {
const self_onlineStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought online");
self_onlineStore.buyArray = this;
};
return this;
})();
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
localStore.buy()
方法显然被 onlineStore.buy()
方法覆盖,因为它们都返回到 Fruit() 方法范围,使用相同的名称,最后一个覆盖第一个一.
那么,在不使用具有这些嵌套方法的对象的情况下允许像 onlineStore 和 localStore 这样的“名称空间”的解决方案是什么?
您正在两个函数中创建一个函数变量。但是 this.onlinestore 覆盖了 fruit 的函数变量。这与 setter 函数没有什么不同。想想你可以用两种不同的方法设置一个变量。从上到下,在在线商店功能中,您覆盖 this.buy 方法。
你可以使用下面的例子。
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = () =>{
console.log('local store');
const self_localStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought locally");
self_localStore.buyArray = this;
};
return this;
};
// Buy from online store
this.onlineStore = () => {
console.log('online store')
const self_onlineStore = this;
this.buyArray = [];
this.buy = function (fruit) {
console.log("Bought online");
self_onlineStore.buyArray = this;
};
return this;
};
return this;
}
let fruit = new Fruit();
fruit.localStore().buy("apple"); // -> Bought online, instead of Bought locally
当你写一个IIFE时,this
等于window
或undefined
(取决于你是否使用严格模式):
(function() { console.log(this === window); })() // True
正在为 this
关键字指定调用函数的对象,例如:
const obj = {
fun: function() { console.log(this === obj); }
}
obj.fun(); // True
如果你想创建一些有自己状态的命名空间,我建议你使用这样一个简单的对象:
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = {
buyArray: [],
buy: function (fruit) {
this.buyArray.push(fruit);
console.log("Bought locally:", this.buyArray.join(', '));
}
};
// Buy from online store
this.onlineStore = {
buyArray: [],
buy: function (fruit) {
this.buyArray.push(fruit);
console.log("Bought online:", this.buyArray.join(', '));
}
};
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
fruit.localStore.buy("banana");
fruit.onlineStore.buy("orange");
但是,您可能不喜欢文字对象,因为它们不提供真正的封装(可以从 buy
函数外部访问 buyArray
属性)。
所以您也可以像您最初尝试做的那样将状态封装在 IIFE 中:
function Fruit() {
const self = this;
this.fruits = [];
this.addFruit = function (fruit) {
self.fruits.push(fruit);
};
// Buy locally
this.localStore = (function() {
const buyArray = [];
const buy = function (fruit) {
buyArray.push(fruit);
console.log("Bought locally:", buyArray.join(', '));
};
return { buy };
})();
// Buy from online store
this.onlineStore = (function() {
const buyArray = [];
const buy = function (fruit) {
buyArray.push(fruit);
console.log("Bought online:", buyArray.join(', '));
};
return { buy };
})();
return this;
}
let fruit = new Fruit();
fruit.localStore.buy("apple"); // -> Bought online, instead of Bought locally
fruit.localStore.buy("banana");
fruit.onlineStore.buy("orange");