【问题标题】:What am I doing wrong when combining objects with the module pattern将对象与模块模式组合时我做错了什么
【发布时间】:2014-02-02 09:52:26
【问题描述】:

这个Possible duplicate对我没有帮助,因为一个类似的问题,我面试失败了。

这个想法是使用module patterninheritance创建一个人Object,他是老师的父亲和经理的祖父。 像那个经理->老师->人

我的代码是这样的(My Plunk):

(function(undef)
{
    /**Waiting till document is ready before applying next functions*/
    $(document).ready(function(){

        var person = new APP.Person('Aria Stark','223232');
        document.write(person.getDetails());
    })();

     var APP = {};

     APP.Person =(function() {

        function Person(name, ID) {
            this.name = name;
            this.ID = ID;
        }

        Person.prototype.getDetails = function() {
            return " name: " + this.name + " ID: " + this.ID;
        };

        return Person;
    });

    APP.Teacher =(function () {

        function Teacher(name, ID, salary, hatColor) {
            APP.Person.call(this, name, ID);
            this.salary = salary;
            this.hatColor = hatColor;
        }

        Teacher.prototype = new APP.Person();

        Teacher.prototype.getDetails = function() {
            return APP.Person.call(this) + " Salary: " + this.salary + " Hat: " + this.hatColor;
        };

        return Teacher;
    });


    APP.Manager =(function () {

        function Manager(name, ID, salary, hatColor, car) {
            APP.Teacher.call(this, name, ID, salary, hatColor);
            this.car = car;
        }

        Manager.prototype = new APP.Teacher();

        Manager.prototype.getDetails = function() {
            return APP.Teacher.call(this) + " Car: " + this.car;
        };

        return Manager;
    });


})(); 

我在第一行得到一个错误:

var person = new APP.Person('Aria Stark','22323');

错误是:Uncaught TypeError: object is not a function

有人可以帮我解决这个问题吗?我也愿意听取对此代码的其他改进。

【问题讨论】:

    标签: javascript function object iife


    【解决方案1】:

    不需要 jQuery 来创建这些东西。好吧,我对此没有很好的揭露,但我试图展示你想知道的东西:

    // Creating Person Class
    var Person = function(name, id){
        this.name = name;
        this.id = id;
    };
    
    Person.prototype.getInfo = function(){
        return "name: " + this.name + ",  id: " + this.id;
    };
    
    // Instance of Person
    var x = new Person("Ashish", 1);
    x.getInfo();
    
    // Creating Teacher Class
    var Teacher = function(name, id, salary, hatColor){
        Person.call(this, name, id);
        this.salary = salary;
        this.hatColor = hatColor;
    };
    
    // Inheriting Persons methods
    Teacher.prototype = new Person();
    
    // Adding new method to it
    Teacher.prototype.getFullDetails = function(){
        return this.getInfo() + ", salary: " + this.salary + ", Hatcolor: " + this.hatColor;
    }
    
    // Instance of Teacher Class
    var teacher = new Teacher("John", 2, 15000, "red");
    teacher.getInfo(); //output: "name: John,  id: 2"
    teacher.getFullDetails(); // output : "name: John,  id: 2, salary: 15000, Hatcolor: red"
    console.log(teacher.salary); // output : 15000
    

    所以,在上面你可以看到: - 一个Person 类是用2 个属性和一个方法创建的。 - 然后我们创建了一个Teacher 类并继承了其中Person 类的方法。 - 然后在其中添加了另一个名为getFullDetails() 的方法,它访问来自Person 类的方法。

    这就是你在 DOM.ready 中所做的事情:

    alert(x.getInfo()); // in my example:
    

    在你的例子中:

    var APP = {};
    APP.Person = function Person(name, ID) {
        this.name = name;
        this.ID = ID;
    }
    
    APP.Person.prototype.getDetails = function () {
        return " name: " + this.name + " ID: " + this.ID;
    };
    
    var person = new APP.Person('Aria Stark', '223232');
    alert(person.getDetails());
    

    【讨论】:

      【解决方案2】:

      这就是您创建(和调用)self-executing function or IIFE 的方式:

      (function () {})();
      

      简单写(function () {})不会调用函数,在这种情况下实际上并没有什么实际作用。以你的方式,APP.Person 将是一个函数,它返回另一个函数(Person 的构造函数)当被调用时 - 它不能与new 一起正常运行。

      另外,对于documentready,你不想执行.ready调用的结果,只需将function作为参数传递,当事件触发时会调用它:

      $(document).ready(function(){
      }); //removed () from here
      

      Plunk with these changes

      【讨论】:

      • 感谢您的回答,但是这个回答导致了一个新问题:plnkr.co/edit/fyg4JDBQp9DSzvI6pvOx?p=preview,当我尝试创建教师对象时
      • @Canttouchit 我会看看。同时,请忘记document.write,还有console.log,非常有用。
      • 是的,忘记了:return APP.Person.prototype.getDetails.call(this)
      • @Canttouchit 是的,还有另一个问题。这就是您在APP.Person 上调用getDetails 的方式:APP.Person.prototype.getDetails.call(this)。请记住,APP.Person 是一个函数,它有一个 prototype 属性,而您将 getDetails 放在那个属性上。 Working Plunk
      【解决方案3】:

      你所有的对象都是这样声明的:

      APP.X=(function() {
          function Y() {}
          Y.prototype.method= function() {};
          return Y;
      });
      

      这本身并没有错,虽然有点奇怪。你想要的是这样的:

      APP.X=(function() {
          function X() {}
          X.prototype.method= function() {};
          return X;
      })(); // actually call the anonymous function you used to encapsulate variables
      

      再一次,你为什么要为 IIFE 烦恼?你也可以这样做:

      APP.X = function () {}
      X.prototype.method= function() {};
      

      封装它们绝对不会带来任何东西,你没有隐藏在外部范围内的任何私有内容。


      另外,我的帖子可能比 StackOverflow 更适合 CodeReview,但您的继承模型存在重大问题。您的 Teacher.prototype 是一个不带参数创建的 Person 实例。只有在高度限制的情况下才会安全。

      更好的模型是这个:

      Teacher = function(){
          Person.call(this /*, person parameters*/);
      }
      Teacher.prototype = Object.create(Person.prototype);
      

      关于 SO 处理这个特定问题有很多很好的答案,here 是我的一个。

      【讨论】:

      • 他从 IIFE 获得的唯一好处是更好的可读性 - 属于一起的东西(构造函数和原型的方法)被分组,它在视觉上变得更容易理解。但当然是 +1。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-01-29
      • 1970-01-01
      • 2019-09-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-30
      相关资源
      最近更新 更多