这个问题和如何在javascript中执行javascript,或者php中的php非常相似,答案是可以eval。如果 php 可以 eval javascript 并且 javascript 可以 eval php,我们就不会有这个讨论了。
为了让 JavaScript 评估 PHP,它必须将 PHP 代码解析为代表脚本的结构。 JavaScript 可以使用 JavaScript 对象表示法(不是 JSON 格式,而是实际表示)轻松地做到这一点,并在功能上分解脚本。
这是一个 JavaScript 解释 PHP 的幼稚示例(更诚实的示例不会那么做作,而是将 php 解析为它自己的类似 JSON 的表示或可能的字节码,然后在 javascript 仿真上解释这个类似 json 的表示或字节码的php虚拟机,但仍然):
(() => {
'use strict';
var phpSnippet = 'echo "Hi";';
var partialPHPEval = (phpCode) => {
var regex = /echo[\s]["]([^"]*)["][;]/mg;
var match = null;
phpCode = phpCode.trim();
if ((match = phpCode.match(regex))) {
var code = (match[0].replace(regex, "(console.log('$1'))"));
console.log('converted to "' + code + '"');
eval(code);
}
};
partialPHPEval(phpSnippet);
})();
问题在于 PHP 不是 javascript,并且它的 eval 比 javascript 的弱得多。
这会产生一个问题,即 php 可以轻松地发出将 javascript 标记为 PHP 的请求:JavaScript 可以轻松地创建任何东西的“JSON 化”版本(只要它不是本机的),因此您可以让 PHP 发送请求到带有您要评估的脚本的 nodejs 服务器。
例如:(PHP代码)
include "some_file_defining_jsEval.php";
$wantedObject = function($a) {
return $a;
};
$resultingObject = jsEval(
'(function(a) {' .
' return a;' .
'})'
);
echo $resultingObject("Hello, World!");
JavaScript 可以通过以下方式轻松地将其评估为“函数对象”:
var functionObject = eval(
'(function(a) {' +
' return a;' +
'})'
);
console.log('your code is: ' + '(' + functionObject.toString() + ')');
正如你所看到的,js 可以很容易地把它解析成一个对象,然后再解析成一个字符串,只是需要添加 '(' 和 ')' 以使其 eval() 不会导致错误"Uncaught SyntaxError: Unexpected token (".
不管怎样,在PHP中也可以做类似的事情:
<?php
$functionObject = eval(
'return function($a) {' .
' return $a;' .
'};'
);
echo $functionObject("hi");
?>
知道了这一点,你必须让 JavaScript 将 JavaScript 函数对象转换为 PHP 函数对象,或者走简单的路线,只进行翻译。
问题在于 JavaScript(ES6) 比 PHP 更具表现力(5.6, 7 可能更好,但如果没有 service pack 1 windows 7 它就无法工作,所以我无法在这台计算机上运行它) .这反过来意味着 JavaScript 有很多功能,PHP 没有,例如:
(function() {
console.log("Hello World");
})();
不适用于 PHP 5.6,因为它不支持自执行函数。这意味着您需要做更多的工作才能将其翻译成:
call_user_func(function() {
echo "hello, world!" . "\n";
});
还有一个问题是 PHP 并没有像 javascript 那样真正使用原型,因此很难翻译它。
无论如何,最终 php 和 javascript 非常相似,以至于您基本上可以在例外情况下使用它们。
例如:(PHP)
/* 据我所知,不能描述为函数,因为不是原型 */
类控制台{
静态函数日志($文本){
回声$文本。 "\n";
}
};
call_user_func(function() {
$myScopeVariable = "嘿,这不是 JavaScript!";
控制台::log($myScopeVariable);
});
例如JavaScript:
/* javascript requires brackets because semicolons are not mandatory */
var almost_echo = (console.log.bind(console));
结论
您可以在 PHP 和 JavaScript 之间进行转换,但是将 PHP 转换为 JavaScript 比将 JavaScript 转换为 PHP 容易得多,因为 JavaScript 本身更具表现力,而 PHP 必须创建类来表示许多 JavaScript 构造(够有趣了,php 可以预处理php 来解决所有这些问题)。
幸运的是,PHP 现在可以原生地理解 JSON,因此在 javascript 评估自身之后,javascript 可以读取结果结构(JavaScript 中的大多数东西是对象或函数),包括源代码,并将这些对象放入 JSON 编码形式。之后,您可以让 PHP 解析 JSON 以通过中性形式恢复代码)。
例如
php: jsEval('function(a){return a;}');
js: [{"type":"function", "name": "foo", "args":["a"], body: "return a"}]
php: oh, i get it, you mean
function foo($a) { return $a; }
本质上,可以说是通过“Common LISP”进行通信。当然,这将非常昂贵并且不是原生的,但是可以演示一个示例。理想情况下,我们将拥有一个封装各种脚本的本机模块,可以轻松地将 ruby 转换为 php 到 perl 到 python 到 javascript,然后将结果编译到 c 中)。 javascript 通过能够评估自己以及打印自己的代码来帮助接近这一点。如果所有语言都可以做到这两件事,那会更容易完成,但遗憾的是 javascript 只是“几乎存在”(没有 un-eval 函数,您可以轻松发明它,但它还没有)
至于更新 DOM。 PHP 可以像 JavaScript 一样轻松地做到这一点。问题是 javascript 和 php 都不知道 DOM 是什么,只是在浏览器中,dom 被方便地挂钩为“窗口”对象。您只需表现得好像窗口就在那里,当 php 被评估为 javascript 时,它将再次获得对 DOM 的访问权限。然而,要使用 dom,代码必须是“面向回调的”,因为它在评估之前不会获得 dom,但这还不错,您只需在评估完成之前不做任何事情,然后执行在 dom 可用后立即执行整个操作。
代码如下所示:
(() => {
var php_code = `
function ($window) {
$window::document::getElementById('myDIV')->innerHTML = "Hello, World!";
};
`;
window.addEventListener('load', () => {
(eval(php_code(window)))();
});
})();
虽然正确的做法是让函数评估为一个承诺(承诺是通用的......只要你用所有语言实现它们......)。在那之后,它就变成了一个处理本质上独立于语言的承诺/意图的问题(具体而言,意图是语言独立的,一旦意图被翻译,意图将需要可能提供或可能不提供的依赖项来实际执行从头到尾的顺序)。
希望有一天我们会看到 JavaScript 可以评估 PHP 和 PHP 可以无缝地评估 JavaScript 的未来,至少可以完成混淆圈,允许我们编写客户端 php 和服务器端 javascript(我们已经成功了一半! )
一些结束的想法
php、perl、lisp 和其他 lambda 演算同义词需要它们自己的内置 JSON 变体。它基本上是 eval 和 uneval 但更简单,因为它不处理更令人兴奋的数据结构,如函数(JavaScript 可以在某种程度上使用 toString 取消评估,Perl 可以使用 Data::Dumper 和 Data::Dumper::Deparse 设置为1).
-
每一种 lambda 演算同义词语言(php、perl、lisp、...,其中声明 (function(a){return function(b){return a + b;}})(2)(3) 是有道理的(天真地,即使汇编也可以通过堆栈挖掘来做到这一点,所以它有点像 lambda 演算同义词语言,并且可以也有它自己的 JSON 变体)应该能够将一串有效代码编码成一个通用的抽象表示,该表示可以被任何其他 lambda 演算同义词语言编码和解码。
- 函数式编程原则规定,每个动作都可以分解为执行动作的请求,“提交列表”的转换,它堆叠提交而不执行它们,然后将提交映射到全局环境的实际转换(或者纯粹的,通过创建一个新环境并进行尾递归/将其放入队列中,并使未来的动作与新环境一起工作;或者不纯粹,通过改变全局状态并继续前进;两者在适当的抽象机制下是等价的)。这意味着您可以在 ajax 请求中发送一个 php 脚本,让服务器在虚拟提交对象上象征性地执行它,然后向客户端返回它需要执行的操作列表,以使其看起来像是执行了 php)。