Вопрос по javascript, prototype – Расширение объекта в Javascript

137

В настоящее время я перехожу из Java в Javascript, и мне немного сложно понять, как расширять объекты так, как я хочу.

Я видел, как несколько человек в интернете использовали метод под названием «расширять объект». Код будет выглядеть так:

<code>var Person = {
   name : 'Blank',
   age  : 22
}

var Robot = Person.extend({
   name : 'Robo',
   age  : 4
)}

var robot = new Robot();
alert(robot.name); //Should return 'Robo'
</code>

Кто-нибудь знает, как заставить это работать? Я слышал, что вам нужно написать

<code>Object.prototype.extend = function(...);
</code>

Но я не знаю, как заставить эту систему работать. Если это невозможно, пожалуйста, покажите мне другую альтернативу, которая расширяет объект.

я также предлагаю не думать об этом строго как о «преобразовании из Java в JavaScript»; и больше как «изучение нового языка, Javascript, который имеет синтаксис, аналогичный Java»; Toni Leigh
Если после прочтения этих хороших документов вам по-прежнему интересноextend функция, я настроил здесь пример:jsfiddle.net/k9LRd Codrin Eugeniu
вернуть истину; но вот почему я спрашиваю :) Wituz
Я хотел бы предложить пройти этот прекрасный учебник по MDN:developer.mozilla.org/en/… Pranav

Ваш Ответ

16   ответов
6

которые все еще борются за простой и лучший подход, вы можете использоватьSpread Syntax для расширения объекта.

var person1 = {
      name: "Blank",
      age: 22
    };

var person2 = {
      name: "Robo",
      age: 4,
      height: '6 feet'
    };
// spread syntax
let newObj = { ...person1, ...person2 };
console.log(newObj.height);

Note: Помните, что свойство, наиболее удаленное справа, будет иметь приоритет. В этом примереperson2 находится на правой стороне, такnewObj будет иметь имяRobo в этом.

0

Object.prototype.extend = function(object) {
  // loop through object 
  for (var i in object) {
    // check if the extended object has that property
    if (object.hasOwnProperty(i)) {
      // mow check if the child is also and object so we go through it recursively
      if (typeof this[i] == "object" && this.hasOwnProperty(i) && this[i] != null) {
        this[i].extend(object[i]);
      } else {
        this[i] = object[i];
      }
    }
  }
  return this;
};

update: I checked for this[i] != null since null is an object

Тогда используйте это как:

var options = {
      foo: 'bar',
      baz: 'dar'
    }

    var defaults = {
      foo: false,
      baz: 'car',
      nat: 0
    }

defaults.extend(options);

Это хорошо приводит к:

// defaults will now be
{
  foo: 'bar',
  baz: 'dar',
  nat: 0
}
12

In ES6, естьObject.assign для копирования значений свойств. использование{} в качестве первого параметра, если вы не хотите изменять целевой объект (первый пройденный параметр).

var resultObj = Object.assign({},Obj1,Obj2);

Для более подробной информации смотрите ссылку,

MDN - Object.assign ()

В случае, если вам нужно этоPolyfill for ES5, ссылка предлагает это тоже. :)

0
Summary:

prototypal inheritance, Прототип наследования используется при поиске свойства объекта. Когда мы расширяем свойства в javascript, мы наследуем эти свойства от реального объекта. Это работает следующим образом:

When an object property is requested, (e.g myObj.foo or myObj['foo']) the JS engine will first look for that property on the object itself When this property isn't found on the object itself it will climb the prototype chain look at the prototype object. If this property is also not found here it will keep climbing the prototype chain until the property is found. If the property is not found it will throw a reference error.

Когда мы хотим расшириться от объекта в javascript, мы можем просто связать этот объект в цепочке прототипов. Есть множество способов добиться этого, я опишу 2 наиболее часто используемых метода.

Examples:

1. Object.create()

Object.create() это функция, которая принимает объект в качестве аргумента и создает новый объект. Объект, который был передан в качестве аргумента, будет прототипом вновь создаваемого объекта. Например:

// prototype of the dog
const dogPrototype = {
  woof: function () { console.log('woof'); }
}

// create 2 dog objects, pass prototype as an argument
const fluffy = Object.create(dogPrototype);
const notFluffy = Object.create(dogPrototype);

// both newly created object inherit the woof 
// function from the dogPrototype
fluffy.woof();
notFluffy.woof();

2. Explicitly setting the prototype property

При создании объектов с использованием функций конструктора мы можем установить свойства add для его свойства объекта-прототипа. Созданные объекты формируют функцию конструктора при использованииnew ключевое слово, их прототип установлен в прототип функции конструктора. Например:

// Constructor function object
function Dog (name) {
   name = this.name;
}

// Functions are just objects
// All functions have a prototype property
// When a function is used as a constructor (with the new keyword)
// The newly created object will have the consturctor function's
// prototype as its prototype property
Dog.prototype.woof = function () {
  console.log('woof');
}

// create a new dog instance
const fluffy = new Dog('fluffyGoodBoyyyyy');
// fluffy inherits the woof method
fluffy.woof();

// can check the prototype in the following manner
console.log(Object.getPrototypeOf(fluffy));

18

Если вам не нравится, как работает прототипирование для расширения объектов / классов, взгляните на это:https://github.com/haroldiedema/joii

Краткий пример кода возможностей (и многих других):

var Person = Class({

    username: 'John',
    role: 'Employee',

    __construct: function(name, role) {
        this.username = name;
        this.role = role;
    },

    getNameAndRole: function() {
        return this.username + ' - ' + this.role;
    }

});

var Manager = Class({ extends: Person }, {

  __construct: function(name)
  {
      this.super('__construct', name, 'Manager');
  }

});

var m = new Manager('John');
console.log(m.getNameAndRole()); // Prints: "John - Manager"
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
2
Function.prototype.extends=function(ParentClass) {
    this.prototype = new ParentClass();
    this.prototype.constructor = this;
}

function Person() {
    this.name = "anonym"
    this.skills = ["abc"];
}
Person.prototype.profile = function() {
    return this.skills.length // 1
};

function Student() {} //well extends fom Person Class
Student.extends(Person)

var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
Update 01/2017:

Пожалуйста, проигнорируйте мой ответ 2015 года, так как теперь Javascript поддерживаетextends ключевое слово с ES6 (Ecmasctipt6)

- ES6 :
class Person {
   constructor() {
     this.name = "anonym"
     this.skills = ["abc"];
   }

   profile() {
    return this.skills.length // 1
   }

}

Person.MAX_SKILLS = 10;
class Student extends Person {


} //well extends from Person Class

//-----------------
var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
- ES7 :
class Person {
    static MAX_SKILLS = 10;
    name = "anonym"
    skills = ["abc"];

    profile() {
      return this.skills.length // 1
    }

}
class Student extends Person {


} //well extends from Person Class

//-----------------
,var s1 = new Student();
s1.skills.push("")
s1.profile() // 2
Error: User Rate Limit Exceedednew ParentClass()Error: User Rate Limit Exceeded
6

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes/extends

ПРИМЕЧАНИЕ. Это экспериментальная технология, часть предложения ECMAScript 6 (Harmony).

class Square extends Polygon {
  constructor(length) {
    // Here, it calls the parent class' constructor with lengths
    // provided for the Polygon's width and height
    super(length, length);
    // Note: In derived classes, super() must be called before you
    // can use 'this'. Leaving this out will cause a reference error.
    this.name = 'Square';
  }

  get area() {
    return this.height * this.width;
  }

  set area(value) {
    this.area = value;     } 
}

Эта технология доступна в Gecko (Google Chrome / Firefox) - ночные сборки 03/2015.

78
World without the "new" keyword. And simpler syntax with Object.create().

который считает, что Javascript должен пытаться жить без «нового». Это бесклассовый язык, ему не нужны конструкторы. Вы просто создаете объекты, а затем расширяете или изменяете их. Конечно, есть подводные камни, но это гораздо мощнее и проще:

// base `Person` prototype
const Person = {
   name : '',
   age  : 22,
   type : 'human',
   greet() {
       console.log('Hi, my name is ' + this.name + ' and I am a ' + this.type + '.' )
   }
}

// create an instance of `Person`:
const skywalker = Object.create(Person)
skywalker.name = 'Anakin Skywalker'
skywalker.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
Extending the base prototype
// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'
Robot.variant = '' // add properties for Robot prototype

// Robots speak in binaries, so we need a different greet function:
Robot.greet = function() { //some function to convert strings to binary }
One more level deeper
// create a new instance `Robot`
const Astromech = Object.create(Robot)
Astromech.variant = 'astromech'

const r2d2 = Object.create(Astromech)
r2d2.name = 'R2D2'
r2d2.greet() // '0000111010101011100111....'

// morphing the `Robot` object doesn't affect `Person` prototypes
skywalker.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'
Further reading

** Обновление 3 октября 18. Принять синтаксис ES6 и использоватьconst а такжеlet, Добавлен пример, чтобы показать, как сделать свойства неизменяемыми.

** Обновление 22 января 17. Включен ES6 Object.assign ().

Как видите, назначение требует нескольких операторов. В ES6 вы можете использовать метод #assign для сокращения назначений. (Для использования polyfill в старых браузерах см.MDN на ES6.)

//instead of this
const Robot = Object.create(Person)
Robot.name = "Robot"
Robot.madeOf = "metal"
Robot.powerConsumption_kW = 5

//you can do this
const Robot = Object.create(Person)
Object.assign(Robot, {
    name: "Robot",
    madeOf: "metal",
    powerConsumption_kWh: 5,
    fullCharge_kWh: 10,
    currentCharge_kWh: 5
})

//attach some methods unique to Robot prototype.
Robot.charge = function(kWh) {
    let self = this
    this.currentCharge_kWh = Math.min(self.fullCharge_kWh, self.currentCharge_kWh + kWh)
    var percentageCharged = this.currentCharge_kWh / this.fullCharge_kWh * 100
    console.log(this.name + (percentageCharged === 100) ? ' is fully charged.' : ' is ' + percentageCharged +'% charged.')
}

Robot.charge(5) // outputs "Robot is fully charged."

Вы также можете использовать второй аргумент Object.create () a.k.a propertiesObject, который я считаю слишком длинным. Единственная причина использовать его вместо #assign - если вам нужен больший контроль над значениями, т. Е. Возможность записи / конфигурирования и т. Д. Обратите внимание, какRobot строго должно быть все сделано из металла.

const Robot = Object.create(Person, {
    madeOf: { 
        value: "metal",
        writable: false,
        configurable: false,
        enumerable: true
    },
    powerConsumption: {
        value: "5kWh",
        writable: true,
        configurable: true,
        enumerable: true   
    }
})

И все прототипыRobot не может быть сделано из чего-то другого.

const polymerRobot = Object.create(Robot)

polymerRobot.madeOf = 'polymer'

console.log(polymerRobot.madeOf) // outputs 'metal'

В этом паттерне есть ошибки, которые могут сработать как «классические». программисты. Тем не менее, я нахожу этот шаблон гораздо более читабельным.

1) #Object.assignError: User Rate Limit Exceeded__proto__Error: User Rate Limit Exceededskywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededObject.assign(Robot, {a:1}Error: User Rate Limit Exceededextend()Error: User Rate Limit Exceededgreet()Error: User Rate Limit Exceeded
8

теки, напримерunderscore.js, у которого естьэто собственная реализацияextend().

И это также хороший способ изучения, взглянув на его исходный код.аннотированная страница исходного кода довольно полезно.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded_.extend()Error: User Rate Limit Exceededlostechies.com/chrismissal/2012/10/05/…
51

используйте ассоциативное свойство объектов JavaScript, чтобы добавить функцию расширения кObject.prototype как показано ниже.

Object.prototype.extend = function(obj) {
   for (var i in obj) {
      if (obj.hasOwnProperty(i)) {
         this[i] = obj[i];
      }
   }
};

Затем вы можете использовать эту функцию, как показано ниже.

var o = { member: "some member" };
var x = { extension: "some extension" };

o.extend(x);
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
27
Different approach: Object.create

я считаю, что следующее - лучший и эффективный способ «наследовать»; от объекта-прототипа Person:

function Person(name){
    this.name = name;
    this.type = 'human';
}

Person.prototype.info = function(){
    console.log("Name:", this.name, "Type:", this.type);
}

function Robot(name){
    Person.call(this, name)
    this.type = 'robot';
}

// Set Robot's prototype to Person's prototype by
// creating a new object that inherits from Person.prototype,
// and assigning it to Robot.prototype
Robot.prototype = Object.create(Person.prototype);

// Set constructor back to Robot
Robot.prototype.constructor = Robot;

Создайте новые экземпляры:

var person = new Person("Bob");
var robot = new Robot("Boutros");

person.info(); // Name: Bob Type: human
robot.info();  // Name: Boutros Type: robot

Теперь, используяObject.create:

Person.prototype.constructor !== Robot

Проверьте такжеMDN документация.

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededdeveloper.mozilla.org/en-US/docs/Web/JavaScript/…
Error: User Rate Limit Exceededjsfiddle.net/3brm0a7a
Error: User Rate Limit ExceedednameError: User Rate Limit Exceededjsfiddle.net/3brm0a7a/3Error: User Rate Limit Exceeded
0

PLEASE ADD REASON FOR DOWNVOTE

No need to use any external library to extend

In JavaScript, everything is an object (except for the three primitive datatypes, and even they are automatically wrapped with objects when needed). Furthermore, all objects are mutable.

Class Person in JavaScript

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype = {
    getName: function() {
        return this.name;
    },
    getAge: function() {
        return this.age;
    }
}

/* Instantiate the class. */
var alice = new Person('Alice', 93);
var bill = new Person('Bill', 30);

Modify a specific instance/object.

alice.displayGreeting = function() 
{
    alert(this.getGreeting());
}

Modify the class

Person.prototype.getGreeting = function() 
{
    return 'Hi ' + this.getName() + '!';
};

Or simply say : extend JSON and OBJECT both are same

var k = {
    name : 'jack',
    age : 30
}

k.gender = 'male'; /*object or json k got extended with new property gender*/

Росс Хармс, Дастин Диаз

-1

ами параметров объекта, не изменяя переданный объект.

function extend(object) {
    if (object === null)
        throw TypeError;
    if (typeof object !== "object" && typeof object !== "function")
        throw TypeError;
    if (Object.create)
        return Object.create(object);
    function f() {}
    ;
    f.prototype = p;
    return new f();
}

Но если вы хотите расширить свой объект без изменения его параметров, вы можете добавить exteProperty к своему объекту.

var Person{
//some code
extend: extendProperty
}

//Enforce type checking an Error report as you wish
    function extendProperty(object) {
        if ((object !== null && (typeof object === "object" || typeof object === "function"))){
            for (var prop in object) {
                if (object.hasOwnProperty(prop))
                    this[prop] = object[prop];
            }
        }else{
            throw TypeError; //Not an object
        }
    }
186

Edit:
пожалуйста, проверьте комментарии от пользователя 2491400, в которых сообщается о побочных эффектах простого назначенияprototype.

Original answer:

Вы хотите "наследовать" от объекта-прототипа Person:

var Person = function(name){
  this.name = name;
  this.type = 'human';
}

Person.prototype.info = function(){
  console.log("Name:", this.name, "Type:", this.type);
}

var Robot = function(name){
  Person.apply(this,arguments)
  this.name = name;
  this.type = 'robot';
}

Robot.prototype = Person.prototype;        // Set prototype to Person's
Robot.prototype.constructor = Robot;   // Set constructor back to Robot

person = new Person("Bob");
robot = new Robot("Boutros");

person.info();
// Name: Bob Type: human

robot.info();
// Name: Boutros Type: robot
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededPerson()Error: User Rate Limit Exceedednew Robot()Error: User Rate Limit Exceededthis.name = name;Error: User Rate Limit ExceededRobot()Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
Error: User Rate Limit ExceededPerson.apply(this, arguments);Error: User Rate Limit ExceededRobot.prototype = Object.create(Person.prototype);Error: User Rate Limit Exceedednew Person();.
Error: User Rate Limit Exceeded
3

подчеркивание, jquery, lodash:extend.

Существует также чистая реализация javascript, которая является частью ECMAscript 6:Object.assign: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

Error: User Rate Limit Exceeded
Error: User Rate Limit Exceeded
-2

но иногда прототип довольно опасен и может привести к ошибкам. Я предпочитаю инкапсулировать это в базовый объект, как это делает Ember.js для Ember.Object.extend и Ember.Object.reopen. Это гораздо безопаснее в использовании.

Я создал суть с тем, как вы бы настроить что-тоsimilar к тому, что использует Ember.Object.

Вот ссылка:https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd

Error: User Rate Limit Exceededinfamous prototype frameworkError: User Rate Limit Exceededmight abuse the prototype language feature.
Error: User Rate Limit Exceededdeveloper.mozilla.org/en/docs/Web/JavaScript/…Error: User Rate Limit Exceeded
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.Error: User Rate Limit Exceeded
Error: User Rate Limit Exceededjsfiddle.net/fo6r20rg
Error: User Rate Limit ExceededObjectError: User Rate Limit Exceededrepeat()Error: User Rate Limit ExceededObjectError: User Rate Limit ExceededStringError: User Rate Limit Exceeded

Похожие вопросы