在带有 signalr 的网站中使用原型会导致 'hasSubscriptions' 不是函数

using prototypes in website with signalr causes 'hasSubscriptions' is not a function

我有一个运行良好的网站,但是当我尝试向其添加信号器集线器时出现错误

Uncaught TypeError: this.hasSubscriptions is not a function
at Function.<anonymous> (jquery.signalR-2.2.0.js:2878)
at Function.each (jquery-2.1.4.js:382)
at hubConnection.fn.init.<anonymous> (jquery.signalR-2.2.0.js:2877)
at hubConnection.fn.init.<anonymous> (jquery.signalR-2.2.0.js:759)
at hubConnection.fn.init.dispatch (jquery-2.1.4.js:4435)
at hubConnection.fn.init.elemData.handle (jquery-2.1.4.js:4121)
at Object.trigger (jquery-2.1.4.js:4350)
at jQuery.fn.init.triggerHandler (jquery-2.1.4.js:4907)
at hubConnection.fn.init.start (jquery.signalR-2.2.0.js:652)
at connection._.deferredStartHandler (jquery.signalR-2.2.0.js:463)

查询 signalr 库中的第 2878 行让我发现 this 是我在另一个脚本中定义的原型

Object.prototype.myfunction = function(){
    ...
}

首先,我不明白为什么要询问此原型函数以获取信号器订阅。

其次,如何在不删除原型和重写网站代码的情况下解决这个问题?

注:

我尝试为 hasSubscriptions 添加原型,但这会导致处理我现有原型的其他错误

此外,如果删除原型,信号器周围的所有代码都可以正常工作(但这会破坏站点的其余部分)

实际代码:

<div ng-show="noPartialView()" class="well well-lg">
    <div class="row" data-bind="foreach:counters">

        <div class="col-md-12 canvas-container">
            <h2 data-bind="text:name" class="graph-header"></h2>
            <div data-bind="foreach:lines">
                <div class="indicatorLine inline" data-bind="style:{borderColor:color}"><img /></div>
                <span data-bind="text:name"></span>
            </div>
            <canvas width="1700" height="200" data-bind="attr:{'id': name}" class="responsive-canvas"></canvas>
        </div>

    </div>
</div>

@Scripts.Render("~/bundles/jquery")
<script src="~/SignalR/hubs"></script>
@Scripts.Render("~/bundles/angular")
@Scripts.Render("~/bundles/realtimedata")
@Scripts.Render("~/bundles/AngularMVCApp")

其中捆绑包是:

bundles.Add(new ScriptBundle("~/bundles/jquery")
            .Include("~/Scripts/jquery-2.1.4.js")
            .Include("~/Scripts/jquery.signalR-2.2.0.js")
            .Include("~/Scripts/jquery.color-2.1.2.js"));

        bundles.Add(new ScriptBundle("~/bundles/angular")
            .Include("~/Scripts/angular.js")
            .Include("~/Scripts/angular-sanitize.js")
            .Include("~/Scripts/angular-bootstrap-confirm.js")
            .Include("~/Scripts/angular-animate.js")
            .Include("~/Scripts/angular-ui/ui-bootstrap-tpls.js")
            .Include("~/Scripts/angular-route.js")
            .Include("~/Scripts/datetime-picker.js")
            .Include("~/Scripts/angular-locale_en-gb.js")
            .Include("~/Scripts/moment-with-locales.js"));

        bundles.Add(new ScriptBundle("~/bundles/bootstrap")
            .Include("~/Scripts/bootstrap.js"));

        bundles.Add(new ScriptBundle("~/bundles/realtimedata")
                .Include("~/Scripts/knockout-2.3.0.js")
                .Include("~/Scripts/smoothie.js")
                .Include("~/Scripts/realtimedata.js"));

       bundles.Add(new ScriptBundle("~/bundles/AngularMVCApp")
                .Include("~/Scripts/Helpers.js")
                .Include("~/Scripts/InFill.js")
                .Include("~/Scripts/ArrayComparer.js")
                .IncludeDirectory("~/Scripts/Providers", "*.js")
                .IncludeDirectory("~/Scripts/Directives", "*.js")
                .IncludeDirectory("~/Scripts/Services", "*.js")
                .IncludeDirectory("~/Scripts/Controllers", "*.js")
                .Include("~/Scripts/AngularMVCApp.js"));

实时数据库是

(function () {

var countersHub = $.connection.countersHub;
$.connection.hub.logging = true;
$.connection.hub.start();

countersHub.client.newCounters = function (counters) {
    model.addCounters(counters);
};

....
}());

但问题是由添加到对象(在 Helpers.js 中定义)的任何原型函数引起的,例如

Object.prototype.getFieldValue = function () {
if (arguments == null || arguments.length != 1) {
    return null;
}

var fieldName = arguments[0];

if (this == null || fieldName == null || typeof fieldName != 'string') {        
    return null;
}

var temp = this;
var fieldNameSplit = fieldName.split('.');

for (i = 0; i < fieldNameSplit.length; i++) {
    if (temp == null) {
        return temp;
    }
    if (fieldNameSplit[i].indexOf('[') > -1) {
        var fieldNameWithoutIndex = fieldNameSplit[i].split('[')[0];
        var index = fieldNameSplit[i].split('[')[1].split(']')[0];
        temp = temp[fieldNameWithoutIndex][index];
    }
    else {
        temp = temp[fieldNameSplit[i]];
    }
}
return temp;
};

编辑:找到额外信息

问题看起来是由迭代中公开的对象原型函数引起的

for (i in obj)

然而原生 javascript 原型函数(例如 toString 和 hasOwnObject)不是。

为什么我的原型函数被迭代暴露出来,而原生函数却没有,有没有办法 'mask' 我的函数不作为 iterand 出现?

问题是由于我添加到原型的函数是可枚举的,而底层信号器代码(和 jquery)不在我的控制之下。结果,当在连接 (Function.each (jquery-2.1.4.js:382)) 上寻找集线器时,它也找到了我添加到原型中的功能。

为了解决这个问题,我只需要将原型函数声明为不可枚举的,它就开始工作了:

Object.defineProperty(Object.prototype, "getFieldValue",{
    enumerable:false,
    value: function () {
        ...
    }
});

感谢JS non-enumerable function and How to define method in javascript on Array.prototype and Object.prototype so that it doesn't appear in for in loop的回答