在没有OOP构造的JS中创建对象

时间:2018-11-08 07:12:04

标签: javascript oop

您好,我试图了解如何在JS中创建对象。因此,我尝试使用普通的JS创建以下类。(我知道我无法强化类型),只需将它们放在那里作为参考。

期望的行为

class User{
    name:String;
    age:number;
    function StateCredentials(){
        return "Name:"+this.name+"\r\n"+"Age:"+this.age;
    }
}

我不了解将原型附加到当前对象的顺序以及何时调用apply的实例。实例方法也应放在哪里。

当前实施

User=(function(age,name){
    function User(name,age){
        this.name=name;
        this.age=age;
        this.credentials=SetCredentials;
    }
    function StateCredentials(){
        return "Name:"+this.name+"\r\n"+"Age:"+this.age;
    }
    x={};
    x.__proto__= User.prototype; 
    User.apply(x,[a]); 
    return x;
});

致电

function createObject(){
    u=User(3,3);
    u.StateCredentials();
}

错误Uncaught TypeError: Cannot read property 'StateCredentials' of undefined

作为最后一个说明,我看到了一个实现,其中匿名方法是封装构造函数逻辑的触发器。

(function(){...})(arugments);

3 个答案:

答案 0 :(得分:1)

您的代码有两个问题:

  • User函数不返回任何内容。这就是uundefined的原因,您会收到该错误。您必须添加return x;
  • 即使如此,调用u.StateCredentials();也会失败,因为您永远不会在StateCredentials上创建属性x。您最接近的是创建属性credentials,因此您可以执行u.credentials()
  • 尽管如此,您仍然看不到任何东西,因为您没有对返回值做任何事情。您可以进行console.log(u.credentials())

总体而言,我不太确定您要实现的目标。忽略类示例在语法上的错误,class是“普通JavaScript”。自2015年以来,语法已正式成为该语言的一部分。

我觉得不同的人对“ OPP构造” 的真正含义有不同的理解,所以这里有几个例子。

没有class语法(构造函数+原型)

class或多或少只是语法糖。在幕后,我们处理普通的构造函数。因此,如果您要问等价的前置语法示例是什么样子,它将是这样的:

function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.StateCredentials = function() {
 return "Name:"+this.name+"\r\n"+"Age:"+this.age;
}

var u = new User('foo', 42);
console.log(u.StateCredentials());

因为new会为您完成该操作,所以您无需亲自实例化该对象。


我们自己的new

如果您要问自己如何基本实现new,那将是这样的:

function User(name, age) {
  this.name = name;
  this.age = age;
}

User.prototype.StateCredentials = function() {
  return "Name:" + this.name + "\r\n" + "Age:" + this.age;
}

function newNew(constructor, ...args) {
  var instance = Object.create(constructor.prototype);
  var result = constructor.apply(instance, args);
  if (result && typeof result === 'object') {
     return result;
  }
  return instance;
}

var u = newNew(User, 'foo', 42);
console.log(u.StateCredentials());

注意:我在这里隐式使用rest参数(...args),也可以使用arguments并将其正确切片。

  • Object.create(...)完成了创建具有特定值的原型的新对象的“神奇”过程。
  • constructor.apply(...)只需使用新对象集作为其this值调用构造函数。
  • 然后我们返回构造函数的返回值(如果它是一个对象或我们刚刚创建的对象)。

new

如果您要问的是,如果没有new,构造函数和this,等效项将是什么样子?

var UserPrototype = {
  StateCredentials: function() {
      return "Name:" + this.name + "\r\n" + "Age:" + this.age;
  },
};

function makeUser(name, age) {
  var instance = Object.create(UserPrototype);
  instance.name = name;
  instance.age = age;
  return instance;
}

var u = makeUser('foo', 42);
console.log(u.StateCredentials());

我们仍然需要Object.create来创建一个具有特定值的新对象作为其原型。


没有原型

如果您实际上不想使用原型,则可以改用var instance = Object.assign({}, UserProtoype);合并对象,也可以分别定义和分配方法

function StateCredentials() {
  return "Name:" + this.name + "\r\n" + "Age:" + this.age;
}

function makeUser(name, age) {
  return {
    name: name,
    age: age,
    StateCredentials: StateCredentials,
  };
}

var u = makeUser('foo', 42);
console.log(u.StateCredentials());

当然,可以在StateCredentials内定义makeUser。这是一个优化步骤,因此每次调用makeUser时,我们都会为该函数创建一个新副本。

答案 1 :(得分:1)

或者您可以将类用于较新的浏览器

class User {
  constructor(name, age) {
    this.name = name;
    this.age = age;
  }

  StateCredentials() {
    return "Name:"+this.name+"\r\n"+"Age:"+this.age;
  }
}

let u = new User('name', 31);

console.log(u.StateCredentials());

答案 2 :(得分:0)

您正在使它变得复杂得多:

@Html.DropDownListFor(model => model.names, ViewBag.ListItems as IEnumerable<SelectListItem>, new { style="width:200px; height:35px; margin-left:700px" })

原型随附function user(age,name){ this.name=name; this.age=age; } user.prototype.StateCredentials = function(){ return "Name:"+this.name+"\r\n"+"Age:"+this.age; } var u = new user(12, "Little Billy"); console.log(u.StateCredentials()); var v = new user(11, "Little Suzy"); console.log(v.StateCredentials()); 关键字。 new在这种情况下不使用,尽管您有时会在构造函数中看到某些类型的继承。