【问题标题】:Angularjs: TypeError: Cannot read property _____ of undefinedAngularjs:TypeError:无法读取未定义的属性_____
【发布时间】:2014-10-17 06:52:10
【问题描述】:

我正在创建一个简单的应用程序来自学 Angular,并且我将该应用程序分解为一个主 app.js 以及一个 services.js 和一个 controllers.js。

从 services.js 文件中,我试图从 JSON 中获取数据并将其传递给我的 controller.js,然后简单地将 JSON 中的一个值吐出到 console.log 中。

奇怪的是,将我的服务中的整个数据对象放入控制台会吐出整个对象(抱歉,Chrome 开发人员工具的格式混乱,希望这只是提供一个想法)...

console.log(questions); 在控制台中返回:

Objectconfig: Objectdata: Array[4]0: Objectanswers: Array[4]correctAnswer: "question_1_answers_1"question: "What did Coltrane play?"__proto__: Object1: Objectanswers: Array[4]correctAnswer: "question_2_answers_2"question: "What did Miles play?"__proto__: Object__defineGetter__: function __defineGetter__() { [native code] }__defineSetter__: function __defineSetter__() { [native code] }__lookupGetter__: function __lookupGetter__() { [native code] }__lookupSetter__: function __lookupSetter__() { [native code] }constructor: function Object() { [native code] }hasOwnProperty: function hasOwnProperty() { [native code] }isPrototypeOf: function isPrototypeOf() { [native code] }propertyIsEnumerable: function propertyIsEnumerable() { [native code] }toLocaleString: function toLocaleString() { [native code] }toString: function toString() { [native code] }valueOf: function valueOf() { [native code] }get __proto__: function __proto__() { [native code] }set __proto__: function __proto__() { [native code] }2: Objectanswers: Array[4]correctAnswer: "question_3_answers_4"question: "What did Monk play?"__proto__: Object3: Objectanswers: Array[4]correctAnswer: "question_4_answers_3"question: "What did Ray Brown play?"__proto__: Objectlength: 4__proto__: Array[0]headers: function (name) {arguments: (...)get arguments: function ThrowTypeError() { [native code] }set arguments: function ThrowTypeError() { [native code] }caller: (...)get caller: function ThrowTypeError() { [native code] }set caller: function ThrowTypeError() { [native code] }length: 1name: ""prototype: Object__proto__: function Empty() {}<function scope>status: 200statusText: "OK"__proto__: Object__defineGetter__: function __defineGetter__() { [native code] }__defineSetter__: function __defineSetter__() { [native code] }__lookupGetter__: function __lookupGetter__() { [native code] }__lookupSetter__: function __lookupSetter__() { [native code] }constructor: function Object() { [native code] }hasOwnProperty: function hasOwnProperty() { [native code] }isPrototypeOf: function isPrototypeOf() { [native code] }propertyIsEnumerable: function propertyIsEnumerable() { [native code] }toLocaleString: function toLocaleString() { [native code] }toString: function toString() { [native code] }valueOf: function valueOf() { [native code] }get __proto__: function __proto__() { [native code] }set __proto__: function __proto__() { [native code] }

但是,尝试访问单个值,例如:

console.log(questions[0].correctAnswer);

...给我以下错误:

TypeError: Cannot read property 'correctAnswer' of undefined at new <anonymous> (http://local.testingspace.com/js/global.js:49:33) at invoke (http://local.testingspace.com/js/lib.js:15265:17) at Object.instantiate (http://local.testingspace.com/js/lib.js:15276:23) at $get (http://local.testingspace.com/js/lib.js:18580:28) at link (http://local.testingspace.com/js/lib.js:34222:26) at nodeLinkFn (http://local.testingspace.com/js/lib.js:18010:13) at compositeLinkFn (http://local.testingspace.com/js/lib.js:17404:13) at publicLinkFn (http://local.testingspace.com/js/lib.js:17300:30) at $get.boundTranscludeFn (http://local.testingspace.com/js/lib.js:17424:21) at controllersBoundTransclude (http://local.testingspace.com/js/lib.js:18031:18) <ng-view class="ng-scope">

看看下面的代码,有人知道我为什么会遇到这个问题吗?

谢谢!

-多伦

这里是有问题的代码:

app.js

(function() {

    var JazzQuiz = angular.module('JazzQuiz', ['JazzQuiz.services', 'JazzQuiz.controllers', 'ngRoute']);

    JazzQuiz.config(['$routeProvider', function($routeProvider) {

        $routeProvider
        .when('/', {
            templateUrl: '/partials/quiz.html',
            controller: 'QuizCtrl',
            resolve: {
                questions: function (quizFactory) {
                    return quizFactory.getQuestions();
                },
                responses: function (quizFactory) {
                    return quizFactory.getResponses();

                }
            }
        })
        .when('/score', {
            templateUrl: '/partials/score.html',
            controller: 'ScoreCtrl',
            resolve: {
                responses: function(quizFactory) {
                    return quizFactory.getResponses();
                }
            }
        });

        $routeProvider.otherwise({redirectTo: '/'});

    }]);

})();

services.js

var services = angular.module('JazzQuiz.services' ,[]);

services.factory('quizFactory', ['$http', function($http){
    var resp;
    resp = {
        getQuestions: function (){
            var promise = $http({
                method: 'GET',
                url: '../json/questions.json'
            })
            .success(function (data) {
                return data;
            });
            return promise;

        },
        getResponses: function (){
            var promise = $http({
                method: 'GET',
                url: '../json/submissionResponses.json'
            })
            .success(function (data) {
                return data;
            });
            return promise;
        }
    };

    return resp;
}]);

controllers.js

var ctrl = angular.module('JazzQuiz.controllers', []);

// controller that handles the display of questions and handling of answers
ctrl.controller('QuizCtrl', function ($scope, $http, $location, $rootScope, $timeout, questions, responses){

    $scope.quizContent = questions;
    $scope.quizResponses = responses;

    //this spits out the entire object in the console
    console.log(questions);

    //this gives me an error
    console.log(questions[0].correctAnswer);

    // more to come...
});

questions.json

[
        {
            "question": "What did Coltrane play?",
            "answers": [
                "saxophone",
                "trumpet",
                "guitar",
                "french horn"
            ],
            "correctAnswer": "question_1_answers_1"
        },
        {
            "question": "What did Miles play?",
            "answers": [
                "drums",
                "trumpet",
                "guitar",
                "french horn"
            ],
            "correctAnswer": "question_2_answers_2"
        },  
        {
            "question": "What did Monk play?",
            "answers": [
                "trombone",
                "tabla",
                "drums",
                "piano"
            ],
            "correctAnswer": "question_3_answers_4"
        },
        {
            "question": "What did Ray Brown play?",
            "answers": [
                "saxophone",
                "drums",
                "bass",
                "guitar"
            ],
            "correctAnswer": "question_4_answers_3"
        }                
]

【问题讨论】:

  • 你能记录下整个记录对象的结构吗?
  • 所以,如果questions[0].correctedAnswer 抛出TypeError: Cannot read property 'correctAnswer' of undefined,这意味着questions[0].correctedAnswerundefined。数组为空。
  • 如果你能为此创造一个小提琴会很棒。你也可以分享 console.log(questions);
  • 问题是console.log(questions[0].correctAnswer); 在您的getQuestions 的成功处理程序运行之前返回...
  • 好的,我刚刚添加了整个对象的输出。至于将所有这些都放入 Fiddle 或 Plunkr,我很难让它与所有文件和依赖项一起工作,试图组合东西并在完成后立即发布一个链接,但是当然,在此期间的任何见解都会很酷。 Cerbrus - console.log(questions[0].correctAnswer) 是否有可能在我的 getQuestions 的成功处理程序运行之前返回,即使我在执行 console.log(questions) 时成功获取了整个对象?

标签: javascript json angularjs


【解决方案1】:

查看您的日志输出,我认为您的问题是从 $http 请求的 success 处理程序中返回的值未在承诺链中返回,因此您的 success 处理程序实际上并没有做任何东西,您在控制器中收到的承诺值是整个 $http 响应,而不仅仅是结果数据。尝试像这样更改您的服务:

    getQuestions: function (){
        return $http({
            method: 'GET',
            url: '../json/questions.json'
        })
        .then(function (response) {
            return response.data;
        });
    },
    getResponses: function (){
        return $http({
            method: 'GET',
            url: '../json/submissionResponses.json'
        })
        .then(function (response) {
            return response.data;
        });
    }

看看这是否会有所作为。

本着学习的精神,观察你的错误信息,其实是:

Cannot read property 'correctAnswer' of undefined

请注意,您正在评估的表达式是

questions[0].correctAnswer

这意味着questions 不是未定义的部分——它是questions[0],所以两个问题都是:

  • 一个空数组(因为即使有一个定义的元素也意味着索引 0 将被填充——忽略一些古怪的极端情况)
  • 一个包含未定义值作为其第一个元素的数组(可能,但在这种情况下不太可能)
  • 根本不是数组

有了这一点,并且知道questions 确实有一个定义的值,你可以找出其余的:你的questions 对象具有诸如“数据”、“标题”和“状态”之类的属性,这表明它是$http 响应对象。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-06
    • 2020-10-30
    • 2019-10-09
    • 1970-01-01
    相关资源
    最近更新 更多