- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
如果一个人可以选择以一种或另一种方式设计事物,通常情况下(通过性能、可维护性、可读性、功能性等方式)进行函数链接或使用对象属性访问器进行分层访问更好吗? ,为什么?
它是完全取决于用例,还是通常更优越?
例子:
var foo = bar.get('parent').get('child').get('grandChild')...
// vs
var foo = bar['parent']['child']['grandChild']...
// or
var foo = bar.parent.child.grandChild...
或者是否有更好的方法来完全做到这一点?
请注意,由于源代码缩小、使用的属性值不是有效的 JavaScript 标识符等原因,点符号 .
可能并不总是可行。
因为太笼统了,举个更具体的例子怎么样...
考虑以下...
var animals = {
dogs: {
'Chloe': {
name: 'Chloe',
fetch: function() {},
rollover: function() {},
pups: {
'Charlie': {
name: 'Charlie',
fetch: function() {},
rollover: function() {}
},
'Lily': {
//...
}
}
},
'Toby': {
//...
}
},
cats: {
'Fido': {
name: 'Fido',
meow: function() {},
kittens: {
'Mia': {
name: 'Mia',
meow: function() {}
},
'Shadow': {
//...
}
}
}
}
}
请注意,这是展示层次结构的尝试,并未展示任何原型(prototype)继承,尽管它可能存在(并且可能会出现在示例中)。
在如图所示的层次结构中,可以使用属性访问权限来访问某个 pup,如下所示
var myPup = animals.dogs['Chloe'].pups['Charlie'];
// or
var myPup = animals.dogs.Chloe.pups.Charlie;
// or
var myPup = animals['dogs']['Chloe']['pups']['Charlie'];
这是理想的吗?或者使用函数访问小狗是否有显着的好处
var myPup = animals.dogs('Chloe').pups('Charlie');
最佳答案
我认为您为错误的工作使用了错误的工具。像你那样深度嵌套对象是数据建模的一个非常糟糕的选择。您的数据模型如下所示:
+ animals
|
+--+ dogs
| |
| +--+ Chloe
| | |
| | +--+ Charlie
| | |
| | +--+ Lily
| |
| +--+ Toby
|
+--+ cats
|
+--+ Fido
|
+--+ Mia
|
+--+ Shadow
这种数据模型称为 hierarchical model因为数据是以层级的形式排列的。
分层数据模型不是一个好的数据模型,因为它不提供 access path independence .这仅仅意味着(由于数据建模的方式)不可能在不知道其访问路径的情况下找到给定的对象。
例如Lily
的访问路径是animals.dogs.Chloe.Lily
,Toby
的访问路径是animals .dogs.Toby
.访问路径独立性很重要,因为这意味着您无需担心对象在数据模型中的位置。这使编程更简单,并确保每个对象都将在相同的时间内被访问。
在上面的示例中,访问 Lily
比访问 Toby
花费的时间更多,因为它更深一层。为了说明访问路径依赖如何使编程更加困难,请考虑以下代码:
function findParentOf(animal) {
var dogs = animals.dogs;
for (var dog in dogs)
if (dogs[dog].pups.hasOwnProperty(animal))
return dog;
var cats = animals.cats;
for (var cat in cats)
if (cats[cat].kittens.hasOwnProperty(animal))
return cat;
return null;
}
现在假设您有许多不同类型的动物,例如狗、猫、兔子、仓鼠等。您能看到您拥有的冗余代码量吗?
事实上你的数据模型也有很多冗余。例如,每个对象都有一个 name
,即使它的键具有相同的值。此外,每只狗和小狗都有 fetch
和 rollover
功能,每只猫和小猫都有 meow
功能。
使用正确的抽象,所有这些都可以很容易地概括。例如,这就是我要做的:
function animal(kind, parent, name) {
return {
kind: kind,
parent: parent,
name: name
};
}
var dog = animal.bind(null, "dog", null);
var pup = animal.bind(null, "dog");
var cat = animal.bind(null, "cat", null);
var kitten = animal.bind(null, "cat");
var animals = [
dog("Chloe"),
pup("Chloe", "Charlie"),
pup("Chloe", "Lily"),
dog("Toby"),
cat("Fido"),
kitten("Fido", "Mia"),
kitten("Fido", "Shadow")
];
这种建模数据的方式被称为 relational model .关系模型最好的事情之一是它具有访问路径独立性。因此,您可以轻松找到对象并执行其他任务。例如:
function findAnimal(name) {
return animals.find(function (animal) {
return animal.name === name;
});
}
function findParentOf(name) {
var animal = findAnimal(name);
if (animal) {
var parent = animal.parent;
return parent && findAnimal(parent);
}
}
function findChildrenOf(name) {
return animals.filter(function (animal) {
return animal.parent === name;
});
}
现在我们有了访问路径独立性,我们可以很容易地找到对象。例如:
var lily = findAnimal("Lily");
var toby = findAnimal("Toby");
var fido = findParentOf("Shadow");
var miaAndShadow = findChildrenOf("Fido");
最后说到fetch
、rollover
和meow
函数,可以这样定义:
function fetch(animal) {
if (animal.kind === "dog") {
// do something
}
}
function rollover(animal) {
if (animal.kind === "dog") {
// do something
}
}
function meow(animal) {
if (animal.kind === "cat") {
// do something
}
}
或者更好的是,将它们放入命名空间中。感谢Richard Simpson给了我这个想法:
dog.fetch = function (animal) {
if (animal.kind === "dog") {
// do something
}
};
dog.rollover = function (animal) {
if (animal.kind === "dog") {
// do something
}
};
cat.meow = function (animal) {
if (animal.kind === "cat") {
// do something
}
};
然后你可以这样做:
dog.rollover(findAnimal("Charlie"));
var rolloverDog = compose(dog.rollover, findAnimal);
function compose(f, g) {
return function (x) {
return f(g(x));
};
}
rolloverDog("Charlie");
只是我的两分钱。希望这会有所帮助。
关于JavaScript:函数链接还是属性访问?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26149964/
你能比较一下属性吗 我想禁用文本框“txtName”。有两种方式 使用javascript,txtName.disabled = true 使用 ASP.NET, 哪种方法更好,为什么? 最佳答案 我
Count 属性 返回一个集合或 Dictionary 对象包含的项目数。只读。 object.Count object 可以是“应用于”列表中列出的任何集合或对
CompareMode 属性 设置并返回在 Dictionary 对象中比较字符串关键字的比较模式。 object.CompareMode[ = compare] 参数
Column 属性 只读属性,返回 TextStream 文件中当前字符位置的列号。 object.Column object 通常是 TextStream 对象的名称。
AvailableSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。 object.AvailableSpace object 应为 Drive 
Attributes 属性 设置或返回文件或文件夹的属性。可读写或只读(与属性有关)。 object.Attributes [= newattributes] 参数 object
AtEndOfStream 属性 如果文件指针位于 TextStream 文件末,则返回 True;否则如果不为只读则返回 False。 object.A
AtEndOfLine 属性 TextStream 文件中,如果文件指针指向行末标记,就返回 True;否则如果不是只读则返回 False。 object.AtEn
RootFolder 属性 返回一个 Folder 对象,表示指定驱动器的根文件夹。只读。 object.RootFolder object 应为 Dr
Path 属性 返回指定文件、文件夹或驱动器的路径。 object.Path object 应为 File、Folder 或 Drive 对象的名称。 说明 对于驱动器,路径不包含根目录。
ParentFolder 属性 返回指定文件或文件夹的父文件夹。只读。 object.ParentFolder object 应为 File 或 Folder 对象的名称。 说明 以下代码
Name 属性 设置或返回指定的文件或文件夹的名称。可读写。 object.Name [= newname] 参数 object 必选项。应为 File 或&
Line 属性 只读属性,返回 TextStream 文件中的当前行号。 object.Line object 通常是 TextStream 对象的名称。 说明 文件刚
Key 属性 在 Dictionary 对象中设置 key。 object.Key(key) = newkey 参数 object 必选项。通常是 Dictionary 
Item 属性 设置或返回 Dictionary 对象中指定的 key 对应的 item,或返回集合中基于指定的 key 的&
IsRootFolder 属性 如果指定的文件夹是根文件夹,返回 True;否则返回 False。 object.IsRootFolder object 应为&n
IsReady 属性 如果指定的驱动器就绪,返回 True;否则返回 False。 object.IsReady object 应为 Drive&nbs
FreeSpace 属性 返回指定的驱动器或网络共享对于用户的可用空间大小。只读。 object.FreeSpace object 应为 Drive 对象的名称。
FileSystem 属性 返回指定的驱动器使用的文件系统的类型。 object.FileSystem object 应为 Drive 对象的名称。 说明 可
Files 属性 返回由指定文件夹中所有 File 对象(包括隐藏文件和系统文件)组成的 Files 集合。 object.Files object&n
我是一名优秀的程序员,十分优秀!