在带有 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的回答
我有一个运行良好的网站,但是当我尝试向其添加信号器集线器时出现错误
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的回答