Google 應用程式腳本提供了庫功能,如果您包含專案密鑰,則會將庫添加為全域物件。我正在尋找迭代添加的庫的所有功能。這曾經是可能的犀牛帶回for...in路的發動機。但我無法遍歷庫中的任何屬性v8 引擎。
該檔案說:
在 V8 運行時中,專案及其庫在不同的執行背景關系中運行,因此具有不同的全域變數和原型鏈。
誰能解釋這個物件是如何創建的或如何訪問它的所有屬性?
專案A:
function testLib(prop = 'main') {
const isEnumerable = MyLibrary.propertyIsEnumerable(prop);
const isOwnProperty = MyLibrary.hasOwnProperty(prop);
console.info({ isEnumerable, isOwnProperty }); // { isEnumerable: false, isOwnProperty: true }
console.info(prop in MyLibrary);//true
for (const property in MyLibrary) {
//loop doesn't start
console.info(property);
}
console.info(Object.getOwnPropertyDescriptor(MyLibrary, prop)); //logs expected data:
/*{ value: [Function: main],
writable: true,
enumerable: false,
configurable: true }*/
console.log(Object.getOwnPropertyDescriptors(MyLibrary)); //actual: {} Expected: array of all functions including `main`
}
function testPropDescriptors() {
const obj = { prop1: 1, b: 2 };
console.log(Object.getOwnPropertyDescriptors(obj)); //logs expected data
/*{prop1: { value: 1, writable: true, enumerable: true, configurable: true },
b: { value: 2, writable: true, enumerable: true, configurable: true } }*/
}
我的圖書館(專案 B):
function main(){}
function onEdit(){}
為了重現,
- 單擊此處創建一個新專案- 例如,專案 A
- 創建另一個腳本專案(比如專案 B):
- 添加一個
main在專案 B 中命名的函式和 - 通過單擊右上角的部署來部署它。
- 將其添加到專案 A 中并將其命名為
MyLibrary.
- 添加一個
- 將上面的腳本復制粘貼到專案A中,選擇
testLib函式并點擊運行
uj5u.com熱心網友回復:
問題和解決方法:
我一直在尋找在啟用V8的情況下從客戶端直接檢索庫端的屬性和函式的方法。但不幸的是,我仍然找不到它。所以就我而言,我使用了 2 種解決方法。
使用 Apps Script API 和/或 Drive API 檢索所有腳本。
將屬性和函式包裝在一個物件中。
通過上述解決方法,可以從客戶端檢索庫端的屬性和函式。
解決方法 1:
在此變通方法中,庫端的所有腳本均使用 Apps Script API 和 Drive API 檢索。
示例腳本 1:
在此示例中,使用了 Apps Script API。因此,當您使用此腳本時,請將 Google Cloud Platform 專案鏈接到 Google Apps 腳本專案。Ref并且,請在 API 控制臺啟用 Apps Script API。
const projectIdOflibrary = "###"; // Please set the project ID of the library.
const url = `https://script.googleapis.com/v1/projects/${projectIdOflibrary}/content`;
const res = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " ScriptApp.getOAuthToken()}});
const obj = JSON.parse(res.getContentText())
const functions = obj.files.reduce((ar, o) => {
if (o.name != "appsscript") ar.push(o);
return ar;
}, []);
console.log(functions)
// console.log(functions.map(({functionSet}) => functionSet.values)) // When you want to see the function names, you can use this line.
當此腳本用于您的庫腳本時,
console.log(functions.flatMap(({functionSet}) => functionSet.values))回傳[ { name: 'main' }, { name: 'onEdit' } ].在這種情況下,即使庫是 Google Docs 的容器系結腳本,該腳本也可以作業。
示例腳本 2:
在此示例中,使用了 Drive API。因此,當您使用此腳本時,請在高級 Google 服務中啟用 Drive API。
const projectIdOflibrary = "###"; // Please set the project ID of the library.
const url = `https://www.googleapis.com/drive/v3/files/${projectIdOflibrary}/export?mimeType=application/vnd.google-apps.script+json`;
const res = UrlFetchApp.fetch(url, {headers: {authorization: "Bearer " ScriptApp.getOAuthToken()}});
const obj = JSON.parse(res.getContentText())
const functions = obj.files.reduce((ar, o) => {
if (o.name != "appsscript") ar.push(o.source);
return ar;
}, []);
console.log(functions)
當此腳本用于您的庫腳本時,
console.log(functions)回傳[ 'function main(){}\nfunction onEdit(){}\n' ].在這種情況下,不會自動決議函式名稱。但是 Google Apps Script Project 不需要與 Google Cloud Platform Project 關聯。但是,當庫是 Google Docs 的容器系結腳本時,不能使用此腳本。在這種情況下,當庫只是獨立型別時,可以使用此腳本。請注意這一點。
解決方法 2:
在這個變通方法中,庫端的屬性和函式用一個物件包裝。
示例腳本:庫端
var sample1 = {
method1: function() {},
method2: function() {}
};
var sample2 = class sample2 {
constructor() {
this.sample = "sample";
}
method1() {
return this.sample;
}
}
示例腳本:客戶端
function myFunction() {
const res1 = MyLibrary.sample1;
console.log(res1)
const res2 = Object.getOwnPropertyNames(MyLibrary.sample2.prototype);
console.log(res2)
}
- 在這種情況下,
console.log(res1)并console.log(res2)回報{ method1: [Function: method1], method2: [Function: method2] }和[ 'constructor', 'method1' ]分別。
參考:
- 將 Google Cloud Platform 專案鏈接到新 IDE 的 Google Apps 腳本專案
- 方法:projects.getContent
- 檔案:匯出
uj5u.com熱心網友回復:
Google Apps Script 是 V8 的自定義嵌入,因此它使用 V8 C API 來創建“神奇”物件。最終結果類似于代理:如果您知道屬性的名稱,則可以檢索它;但是沒有內置的方法來列舉庫中的可用函式。(我不知道為什么它是這樣設計的。)
如果您控制有問題的庫,一種可能的解決方法是從那里匯出函式串列:
// MyLibrary:
Object.defineProperty(this, "global", {value: this});
function getExports() {
let result = [];
let descriptors = Object.getOwnPropertyDescriptors(global);
for (let p in descriptors) {
if (descriptors[p].enumerable) result.push(p);
}
return result;
}
// main project:
console.log(MyLibrary.getExports());
(如果您不控制圖書館,@Tanaike 的回答提供了一些建議。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/361443.html
標籤:javascript 谷歌应用程序脚本 图书馆 v8 全局对象
