未捕获的TypeError:无法设置undefined的属性'response'

0 javascript jquery http xmlhttprequest

所以,我有这个我在2015年写的旧代码,它工作得很好,但现在它不是 - 任何想法是什么错?它在使用ajax时似乎在请求函数中,我收到一个错误:

VM3641:326 Uncaught TypeError: Cannot set property 'response' of undefined
at Object.success (<anonymous>:326:48)
at i (jquery.min.js:2)
at Object.fireWith [as resolveWith] (jquery.min.js:2)
at y (jquery.min.js:4)
at XMLHttpRequest.c (jquery.min.js:4) 
Run Code Online (Sandbox Code Playgroud)

错误仍然存​​在的特定代码段:

        if ($canUsejQuery) {
            // Make Request with jQuery
            console.log('jQuery');
            jQuery.ajax({
                type: this.RequestData.type,
                data: {},
                url: this.RequestData.link,
                success: function (response) {
                    console.log(response);
                    this.ResponseData.response = response;
                },
                error: function (err, errCode, errMessage) {
                    this.ResponseData.response = '';
                    this.ResponseData.hasErrors = true;
                    console.log('error');
                }
            });
        }
Run Code Online (Sandbox Code Playgroud)

这是一个奇怪的,它给出了响应,我尝试将其分配为ResponseData,但它没有做到这一点,并说它未定义,但如果我提醒响应,它工作正常,它不是未定义的?

整个代码:

/**
 * @version     1.0.1
 * @copyright   Copyright (C) 2015. All rights reserved.
 * @author      Curtis <[removed]@gmail.com>
 * @license     SEE END OF FILE FOR LICENSE
 * @github      [removed]
 */

/**
 * @section Configuration
 */

/**
 * @name $httpconfiguration
 * @desc These are all the changable settings for the $HttpLib library by Curtis <[removed]@gmail.com>
 * @type {Object}
 * @public
 */
var $httpconfiguration = {
    /**
     * @name upgradeHTTP
     * @desc Should we upgrade non-secure requests (HTTP:) to secure (HTTPS:)?
     * @default true
     * @note Most browsers won't allow non-secure requests to load when using HTTPs
     */
    upgradeHTTP: true,
    /**
     * @name downgradeHTTPs
     * @desc Should we downgrade secure requests to non-secure requests? (HTTPS: to HTTP:)
     * @default false
     * @note It is not advised you change this setting, you should ALWAYS use HTTPS (secure) requests, however this is left in here for testing.
     */
    downgradeHTTPs: false
};

/**
 * @endsection
 */

// DO NOT MODIFY BELOW THIS LINE

/**
 * @name $HttpLib
 * @desc Define the $HttpLib variable
 * @type {mixcase}
 */
var $HttpLib;

/**
 * @section Code for $HttpLib
 */

/**
 * @name $HttpLib
 * @desc The core of the $Http library, includes all functionality and logical operations for making reasonable, fast, efficient web requests
 * @type {Object} $HttpLib
 * @protected
 */
$HttpLib = {
    /**
     * @name triggerError
     * @desc Trigger an error, and determine the logging level based upon the code (severity) supplied.
     * @type {function}
     * @param {Object} $ErrorInformation
     */
    triggerError: function ($ErrorInformation) {
        var code = $ErrorInformation.code;
        /**
         * @schema code
         * @code 1 {Fatal}
         * @code 2 {Warning}
         * @code 3 {Debug}
         */
        switch (code) {
            case 1:
                alert('[' + $ErrorInformation.errorFunc + ']' + $ErrorInformation.message);
                break;
            case 2:
                console.log('[' + $ErrorInformation.errorFunc + ']' + $ErrorInformation.message);
                break;
            case 3:
                console.log('[Debug message from ' + $ErrorInformation.errorFunc + ']' + $ErrorInformation.message);
                break;
            default:
                console.log('[' + $ErrorInformation.errorFunc + ']' + $ErrorInformation.message);
                break;
        }
    },
    /**
     * @name determineBrowser
     * @desc Get the browser Name, Version, and return {object} $Browser to the requesting function
     * @returns {{name: string, version: string}} $Browser
     */
    determineBrowser: function () {
        var nVer = navigator.appVersion;
        var nAgt = navigator.userAgent;
        var browserName = navigator.appName;
        var fullVersion = '' + parseFloat(navigator.appVersion);
        var majorVersion = parseInt(navigator.appVersion, 10);
        var nameOffset, verOffset, ix;

        // In Opera 15+, the true version is after "OPR/"
        if ((verOffset = nAgt.indexOf("OPR/")) != -1) {
            browserName = "Opera";
            fullVersion = nAgt.substring(verOffset + 4);
        }
        // In older Opera, the true version is after "Opera" or after "Version"
        else if ((verOffset = nAgt.indexOf("Opera")) != -1) {
            browserName = "Opera";
            fullVersion = nAgt.substring(verOffset + 6);
            if ((verOffset = nAgt.indexOf("Version")) != -1)
                fullVersion = nAgt.substring(verOffset + 8);
        }
        // In MSIE, the true version is after "MSIE" in userAgent
        else if ((verOffset = nAgt.indexOf("MSIE")) != -1) {
            browserName = "Microsoft Internet Explorer";
            fullVersion = nAgt.substring(verOffset + 5);
        }
        // In Chrome, the true version is after "Chrome"
        else if ((verOffset = nAgt.indexOf("Chrome")) != -1) {
            browserName = "Chrome";
            fullVersion = nAgt.substring(verOffset + 7);
        }
        // In Safari, the true version is after "Safari" or after "Version"
        else if ((verOffset = nAgt.indexOf("Safari")) != -1) {
            browserName = "Safari";
            fullVersion = nAgt.substring(verOffset + 7);
            if ((verOffset = nAgt.indexOf("Version")) != -1)
                fullVersion = nAgt.substring(verOffset + 8);
        }
        // In Firefox, the true version is after "Firefox"
        else if ((verOffset = nAgt.indexOf("Firefox")) != -1) {
            browserName = "Firefox";
            fullVersion = nAgt.substring(verOffset + 8);
        }
        // In most other browsers, "name/version" is at the end of userAgent
        else if ((nameOffset = nAgt.lastIndexOf(' ') + 1) <
            (verOffset = nAgt.lastIndexOf('/'))) {
            browserName = nAgt.substring(nameOffset, verOffset);
            fullVersion = nAgt.substring(verOffset + 1);
            if (browserName.toLowerCase() == browserName.toUpperCase()) {
                browserName = navigator.appName;
            }
        }
        // trim the fullVersion string at semicolon/space if present
        if ((ix = fullVersion.indexOf(";")) != -1)
            fullVersion = fullVersion.substring(0, ix);
        if ((ix = fullVersion.indexOf(" ")) != -1)
            fullVersion = fullVersion.substring(0, ix);

        majorVersion = parseInt('' + fullVersion, 10);
        if (isNaN(majorVersion)) {
            fullVersion = '' + parseFloat(navigator.appVersion);
            majorVersion = parseInt(navigator.appVersion, 10);
        }
        var $Browser = {
            name: browserName,
            version: fullVersion
        };
        return $Browser;
    },
    /**
     * @name determineHTTPMethod
     * @desc Determine the HTTP method used (ie: http or https), and return {string}
     * @param {string} $URLString
     * @returns {string}
     */
    determineHTTPMethod: function ($URLString) {
        /**
         * @task Check if the {string} $URLString is not a string, and if so, throw an error
         * @success continue
         * @error triggerError(); return;
         */
        if (typeof($URLString) != "string") {
            this.triggerError({
                errorFunc: 'determineHTTPMethod',
                message: 'Failed to determine the HTTP method in the {string} $URLString, as the type of $URLString does not appear to be a valid string. Assuming HTTPS',
                code: '2'
            });
            return 'https';
        }
        else {
            if ($URLString.indexOf('http://') > -1) {
                return 'http';
            }
            else if ($URLString.indexOf('https://') > -1) {
                return 'https';
            }
        }
    },
    /**
     * @name hasExternalLibraries
     * @desc Does the web page have external libraries we can use/rely on? If so, log them so we know.
     * @returns {Boolean} $ExternalLibraries
     */
    hasExternalLibraries: function () {
        var $ExternalLibraries = false;
        /**
         * @task Check for known external libraries we can use
         */
        if (typeof(jQuery) != "undefined" || typeof($) != "undefined") {
            return true;
        }
        /**
         * @task Return the result of {Array} $ExternalLibraries
         */
        return $ExternalLibraries;
    },
    /**
     * @name upgradeHttpMethod
     * @desc Should we upgrade HTTP to HTTPS?
     * @param {string} $URLString
     * @returns {String} $URLString
     */
    upgradeHttpMethod: function ($URLString) {
        if ($httpconfiguration.upgradeHTTP) {
            return $URLString.replace('http:', 'https:');
        }
        return $URLString;
    },
    /**
     * @name downgradeHttpsMethod
     * @desc Should we downgrade HTTPs to HTTP?
     * @param {string} $URLString
     * @returns {string} $URLString
     */
    downgradeHttpsMethod: function ($URLString) {
        if ($httpconfiguration.downgradeHTTPs) {
            console.error('It is not recommended to downgrade HTTPs to HTTP, however the site administrator has enforced the HTTPs downgrade method.');
            return $URLString.replace('https:', 'http:');
        }
        return $URLString;
    },
    /**
     * @name RequestData & ResponseData
     * @desc Request, Response data
     */
    RequestData: {},
    ResponseData: {},
    /**
     * @name request
     * @desc The code to make the proper request, determine what browser, etc. and choose the fastest, best method to obtain the content
     * @param {object} $RequestData
     * @returns {object} $ResponseData
     */
    request: function ($RequestData) {
        /**
         * @name RequestData
         * @desc The request data to set in the {object} this.RequestData
         * @type {string} $ResponseData
         */
        this.RequestData = $RequestData;
        this.ResponseData = this.RequestData;
        /**
         * @name $Browser
         * @desc Obtain the Browser details from {function} determineBrowser
         * @type {Object} $Browser
         */
        var $Browser = this.determineBrowser();
        /**
         * @name $ExternalLibraries
         * @desc Obtain the details of any/all external libraries used that we look for (ie: DownloadJS, jQuery, etc)
         * @type {Array} $ExternalLibraries
         */
        var $ExternalLibraries = this.hasExternalLibraries();

        /**
         * @task Check if {Boolean} $ExternalLibraries is empty or invalid type of {mixcase} instead of {array}
         */
        if ($ExternalLibraries === '' || typeof($ExternalLibraries) != "boolean") {
            /**
             * @task Set {Boolean} $ExternalLibraries to an error since it's not or it's invalid
             * @type {Boolean}
             */
            $ExternalLibraries = false;
        }

        /**
         * @task Determine if we have jQuery
         */
        /**
         * @name $canUsejQuery
         * @desc {boolean} to determine if we can use jQuery or not
         * @type {boolean}
         */
        var $canUsejQuery = true;

        if (!$ExternalLibraries) {
            $canUsejQuery = false;
        }

        console.log($canUsejQuery);
        console.log($ExternalLibraries);

        /**
         * @task Check RequestData to see if we should upgrade, and check our configuration
         */
        if ($RequestData.httpLibUpgrade) {
            $httpconfiguration.upgradeHTTP = $RequestData.httpLibUpgrade;
        }

        $RequestData.link = this.upgradeHttpMethod($RequestData.link);
        $RequestData.link = this.downgradeHttpsMethod($RequestData.link);
        var $httpMethod = this.determineHTTPMethod($RequestData.link);

        if ($httpMethod.indexOf('http:') > -1) {
            console.error('This request to ' + $RequestData.link + ' is considered insecure because it is using http:, soon browsers will block http: requests entirely for security, please enforce an upgrade to HTTPs for security');
        }

        /**
         * @task Make request
         */

        if ($canUsejQuery) {
            // Make Request with jQuery
            console.log('jQuery');
            jQuery.ajax({
                type: this.RequestData.type,
                data: {},
                url: this.RequestData.link,
                success: function (response) {
                    console.log(response);
                    this.ResponseData.response = response;
                },
                error: function (err, errCode, errMessage) {
                    this.ResponseData.response = '';
                    this.ResponseData.hasErrors = true;
                    console.log('error');
                }
            });
        }
        else {
            // Make Request using old way for older browsers/customs browsers/browsers we couldn't detect reliably
            var $xmlHttp = new XMLHttpRequest();
            $xmlHttp.onreadystatechange = function () {
                if ($xmlHttp.readyState == "4" && $xmlHttp.status == 200) {
                    this.ResponseData.response = $xmlHttp.responseText;
                    console.log('success');
                }
                else if ($xmlHttp.readyState == "4" && $xmlHttp.status == 500 || $xmlHttp.readyState == "4" && $xmlHttp.status == 403 || $xmlHttp.readyState == "4" && $xmlHttp.status == 404 || $xmlHttp.readyState == "4" && $xmlHttp.status == 503) {
                    this.ResponseData.response = '';
                    this.ResponseData.hasErrors = true;
                    console.log('error');
                }
            };
            $xmlHttp.open(this.RequestData.type, this.RequestData.link, true);
            $xmlHttp.send(null);
        }

        return this.ResponseData;
    }
};

/**
 * @endsection
 */

/**
 * @section License
 */

/**
 * The code written by Curtis <[removed]@gmail.com> hereinby referred to as "the code" or "code" or "logical functionality"
 * The author Curtis hereinby referred to as "the author" or "author" or "code creator"
 * -------------------------------------------------------------------------------------------------------------------------
 * The author reserves all rights to the code written by the author, however the code is available for all to use, as long as they leave the proper license credits.
 * The author reverses the right to change this license without prior notification.
 * The author permits usage of Http.js for commercial businesses, corporates, enterprises, and businesses of any size.
 * The author permits usage of Http.js for personal/private websites/projects, as long as the license is not violated.
 * The user of the code must leave the license as-in without modification, and must give creation credits if the code is modified in any way/shape/form.
 */

/**
 * @endsection
 */
Run Code Online (Sandbox Code Playgroud)

Don*_*own 5

那是因为this内部successerror回调this在它之外是不一样的.所以ResponseData碰巧是undefined因为它没有response财产.尝试使用bind():

success: function (response) {
    console.log(response);
    this.ResponseData.response = response;
}.bind(this),
error: function (err, errCode, errMessage) {
    this.ResponseData.response = '';
    this.ResponseData.hasErrors = true;
    console.log('error');
}.bind(this)
Run Code Online (Sandbox Code Playgroud)

bind()将使回调的范围设置为您之前的范围this.