是否有可能隐藏Javascript对象的原型!这背后的神秘是什么?

时间:2014-04-11 06:51:28

标签: oop prototype javascript sapui5

我使用的是openui5。有一个用于UI控件的构造函数Button,无法看到Button的原型属性,但在浏览器控制台中执行时显示相同的东西,显示出来!

 sap.m.Button.prototype.Move = function(){
  console.log('Move');
} 
var oButton = new sap.m.Button({text:"Hello"});
oButton.Move(); // throws undefined function! 

在控制台中执行浏览器时的相同代码,它可以工作!

jsbin - >的 http://jsbin.com/tepum/1/edit

3 个答案:

答案 0 :(得分:3)

运行代码后,我发现创建sap.m.Button的第一个实例会导致脚本更改sap.m.Button的原型。它在JavaScript中有效但如果你问我则不是很聪明。

第一次创建会导致同步请求(也不会没有)来获取library-parameters.json。

如果第二次运行代码,它将具有prototype.move,因为创建Button实例不会更改Button.prototype。

Move中的大写M会建议一个构造函数,所以我建议将它改为小写。

由于获取参数是同步的,您可以创建第一个实例,然后设置原型:

console.log("First Button creation changes Button.prototype");
var oButton = new sap.m.Button({text:"Hello"});
sap.m.Button.prototype.move = function(){
  console.log('Move');
} 
oButton.placeAt('content');
oButton.move(); // logs Move

我的猜测是,这是对延迟加载控件完成的,如果从未创建Button,则永远不会为这些未使用的控件加载json配置文件。但它有一些缺点。

  1. 您必须先设置实例,然后才能设置原型。
  2. 配置文件是同步加载的,因此在使用慢速连接创建许多控件的第一个实例时,会导致应用无响应。
  3. 更好的方法是让工厂函数返回一个promise,这样你就可以每次都以相同的方式创建控件,并且可以异步获取配置文件。

    <强> [更新]

    查看配置它似乎是整个gui库的配置,所以我无法看到为什么只在创建第一个实例后才加载它。在创建实例时更改它的对象定义的库不容易扩展,因为它是不可预测的。如果它只是在第一次创建时改变原型,那么它应该没问题,但看起来图书馆的制作者并不希望人们扩展它,或者它们不会使对象定义变得不可预测。如果有可用的api文档,那么可能会尝试检查。

    <强> [更新]

    似乎&#34;正确&#34;扩展控件的方法是使用extend

答案 1 :(得分:3)

@HMR正确扩展控件的正确方法是使用UI5托管对象提供的扩展函数,请参阅http://jsbin.com/linob/1/edit

在下面的示例中,当由其他人调试时,您会注意到控件在需要时是延迟加载的,您之前所做的任何更改都会在加载时丢失

    jQuery.sap.declare("my.Button");
    jQuery.sap.require("sap.m.Button");
    sap.m.Button.extend("my.Button", {
        renderer: {} 
    });

    my.Button.prototype.Move = function() {
        console.log('Move');
    };

    var oButton = new my.Button({
        text: "Hello"
    });
    oButton.placeAt('content');
    oButton.Move();

答案 2 :(得分:2)

它本身并没有隐藏原型。如果构造函数正常退出,那么您将获得该函数的原型。但是,如果一个构造函数实际上返回了一些其他对象,那么你得到了另一个对象的原型,所以假设只是因为你添加到Button原型,当你调用新的Button()时你将会看到你的方法是无效的。你回来了。我敢肯定,如果你对代码进行去混淆,你会发现你正在调用的构造函数在它的末尾有一个“返回新的SomeOtherInstanceOfButton()”或类似代码。

编辑:好的,看看在sap代码中真正发生了什么有点困难,但看起来他们的代码会覆盖控件的原型以向他们添加功能,例如:sap.ui.core.EnabledPropagator ,直到你实际实例化一个按钮,这些东西才会运行。因此,如果您更改代码以实例化页面上的按钮,然后添加到它的原型,然后构造并调用该方法,它工作正常。像这样:

http://jsbin.com/benajuko/2/edit

所以我想我的答案是,当你从控制台运行它时,它已经完成了原型的修复,而在你的测试中,你正在添加原型,然后第一次构建按钮(这会再次改变原型)然后试着打电话给你的旧电话,而不再存在。