扩展JavaScript String和JQuery.ajax

时间:2014-08-20 12:17:46

标签: javascript jquery ajax

最近两天,我试图了解我的代码中的一个问题。

代码在这里: http://jsfiddle.net/a7wkpngr/

String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
};



$.ajax({
    url: '/',
    data: $.extend({}, "")
})

如果您尝试运行此代码,则可以看到

TypeError: undefined is not a function // of course, coz this === window

我试图找到"为什么"。我发现,那个:

  1. 问题出在$.extend中(如果第二个参数是对象,则没有例外)。
  2. 如果您在没有$.extend的情况下运行$.ajax,一切正常
  3. 没有关于Jquery源代码的大概。
  4. 所以,问题是 - String.capitalize()的运行方式和原因。

    P.S。我知道,我知道,扩展本地类是非常糟糕的。

3 个答案:

答案 0 :(得分:2)

通过调试代码,您可以看到,在使用带空选项的扩展时,它将在jquery源代码(版本2.0.1)中转到第201行。

如果你在这里放置断点,那么调用ajax扩展时。参数长度为2.一个是{},另一个是#34;"。

for ( ; i < length; i++ ) {
    // Only deal with non-null/undefined values
    if ( (options = arguments[ i ]) != null ) {
        // Extend the base object
        for ( name in options ) {
            src = target[ name ];
            copy = options[ name ];

在这里循环使用属性(选项中的名称),迭代String的属性,所以实际上它应该添加所有字符串属性,但它只添加你添加的大写函数并将其返回到ajax参数。第一个for循环只执行一次,因为如果长度2和内部只运行一次,即在大写方法上。

现在检查以下输出:

String.prototype.capitalize = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
};

String.prototype.capitalize2 = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
};
String.prototype.trim = function() {
    return this.charAt(0).toUpperCase() + this.slice(1);
};
Object.defineProperty(String.prototype, 'test',
{
    value: function(){ return "test" },
    enumerable: false
});

Object.defineProperty(String.prototype, 'test2',
{
    value: function(){ return "test" },
    enumerable: true
});

for (var key in "") {

console.log(key);
}

控制台输出:

大写
capitalize2
test2

这导致你只是通过可枚举的属性进行迭代。

在此检查jsfiddle:http://jsfiddle.net/w9kdp96a/1/

来自mozilla:

  

for..in语句遍历一个的可枚举属性   对象,以任意顺序。对于每个不同的属性,语句都可以   被执行。

因此,如果您将大写方法定义为

Object.defineProperty(String.prototype, 'capitalize',
{
    value: function(){ return this.charAt(0).toUpperCase() + this.slice(1); },
    enumerable: false
});

它不会在ajax数据中。

答案 1 :(得分:1)

一些事情:

  1. toUpperCase()是JavaScript。例如,请参阅here
  2. 您可以看到您的原型函数使用console.log('hello'.capitalize());
  3. $ .extend的目的是合并到对象,因此你的第二个参数被破坏了:
  4.     $.ajax({
            url: '/',
            data: $.extend({}, {"hello":"world"})
        })
    

    将导致data: {"hello","world"}作为$.ajax()来电的一部分。

    错误是由$ .extend()的第二个参数引起的,它是一个字符串,而不是一个对象。

答案 2 :(得分:1)

在评论中回答您的问题:only question is how and why String.capitalize runs,

如果你看到jquery source它将获取每个数据键(foreach(数据中的东西))并尝试用它创建一个查询字符串。

如果它是一个函数,它将调用它(注释来自jquery源代码):

var prefix,
    s = [],
    add = function( key, value ) {
        // If value is a function, invoke it and return its value
        value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value );
        s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
    };

SSA的答案可能是一个解决方案,但Object.defineProperty仅适用于IE9 and up