使用"其中"在Javascript for Automation中的数组上

时间:2014-11-22 01:16:41

标签: applescript osx-yosemite javascript-automation

使用脚本编辑器使用新的JS进行自动化。我在以下最后一行收到错误:

var iTunes = Application("iTunes");
var sources = iTunes.sources();
var library = sources.whose({name : "Library"});

确认sources数组符合预期(两个元素,一个带name" Library"一个" Internet Radio")。但最后一行与Error on line 3: TypeError: undefined is not a function (evaluating 'sources.whose({name : "Library"})')窒息。

据我所知,我是using the right syntax for the whose function。 (我也尝试使用明确的_equals子句来得到相同的结果。)我做错了什么?

4 个答案:

答案 0 :(得分:8)

  

我做错了什么?

简短回答:这不是你的错。 JXA文档是一堆谎言。

更长的解释:对象的元素 与数组无关。它们表示对象图中的一对多关系,在这种情况下,在source对象与零个或多个library对象之间。

虽然许多关系可能反映了底层实施的遏制等级,但没有义务这样做;例如Finder允许您以多种方式识别桌面上的对象:

items of folder "Desktop" of folder "jsmith" of folder "Users" of disk "Macintosh HD" of app "Finder"
items of folder "Desktop" of folder "jsmith" of folder "Users" of startup disk of app "Finder"
items of folder "Desktop" of home of app "Finder"
items of folder "Macintosh HD:Users:jsmith:Desktop" of app "Finder"
items of desktop of app "Finder"
items of app "Finder"
[etc.]

基于Apple事件的应用程序脚本基于远程过程调用以及简单的一流查询。它的不是 OOP,无论表面外观如何:这只是语法上的糖,使其查询易于读写。

...

在这种情况下,您的第二行是告诉iTunes获取一个查询对象(ObjectSpecifiers)列表(Array),用于标识iTunes应用程序中的每个source对象:

var iTunes = Application("iTunes");
var sources = iTunes.sources();

一旦你有了一个数组,你就无法用它来构建更多的查询,因为JavaScript本身并不知道如何构建查询。你真正想要的是这个:

var iTunes = Application("iTunes");
var sourcesSpecifier = iTunes.sources;
var librarySpecifier = sourcesSpecifier.whose({name : "Library"});

这将为您提供一个对象说明符,用于标识名称为" Library"的所有source个对象。 (如果您只想指定名为" Library"的第一个 source对象,请使用byName方法代替whose;它&# 39;更简单。)

-

就个人而言,我认为所有这些都是学术性的,因为JXA的Apple事件桥实现,就像它的文档一样,主要是由Lame和Fail组成。它主要是在一定程度上工作,然后在你之上大肆宣传。如果您的需求适中,而且足够好"为你做更多的力量,但对于AppleScript的任何非常重要的事情:它是唯一可行的支持解决方案。

(AppleScript / JXA团队也没有理由做这样的废话工作:几个月前我给他们发了一个几乎完成的JavaScriptOSA参考实现,他们希望学习或偷窃,他们完全忽略了。所以你会这样做请原谅我的小气,因为很久以前这是solved problem。)

答案 1 :(得分:2)

这现在可以像理论预测的那样起作用。

(function () {
    'use strict';

    var iTunes = Application('iTunes'),
        filtered = iTunes.sources.whose({
            name: 'Library'
        });

    return filtered().length;

})();

答案 2 :(得分:0)

根据JavaScript for Automation Release Notes Mail.inbox.messages.whose(...)示例,以下内容应该有效:

var iTunes = Application('iTunes');
var filtered = iTunes.sources.whose({name : 'Library'});

带有“包含查询的对象”的“特殊whose方法”的明显目标是通过仅将OS X对象层次结构中的选择项(或项引用)引入生成的JavaScript数组来实现高效

然而,......早期的OS X v10.10版本中,JXA的whose功能似乎有一些错误。

因此,由于所讨论的阵列很小(即2个项目),因此可以快速完成过滤。在将元素作为JS数组获取后,可靠地在JavaScript端。

解决方法示例1

var iTunes = Application('iTunes');
var sources = iTunes.sources();
var librarySource = null;
for (key in sources) {
    var name = sources[key].name();
    if (name.localeCompare("Library") == 0) {
        librarySource = sources[key];
    }
}

解决方法示例2

var iTunes = Application('iTunes');
var sources = iTunes.sources();
function hasLibraryName(obj) {
    var name = obj.name();
    if (name.localeCompare("Library") == 0) {
        return true;
    }
    return false;
}
var filtered = sources.filter(hasLibraryName); 

答案 3 :(得分:0)

In OS X 10.11.5 this seems to be working just fine.

library = Application("iTunes").sources.whose({name:'Library'})()[0]

library.properties()

// {"class":"source", "id":64, "index":1, "name":"Library", "persistentID":"2D8F973150E0A3AD", "kind":"library", "capacity":0, "freeSpace":0}

Note the addition of () after the whose clause to resolve the object specifier into an array of references and then the [0] to get the first (and only, in my case) library object reference, which can then be used to get the properties of that library.

In case the source is not named "Library" in other languages or regions, I would probably use this instead:

library = Application("iTunes").sources.whose({kind:"kLib"})()[0]