Javascript'te Nesne Genişletme


164

Şu anda Java'dan Javascript'e dönüştürüyorum ve nesneleri yapmak istediğim şekilde nasıl genişleteceğimi anlamak benim için biraz zor.

İnternette birkaç kişinin nesneye genişletme denilen bir yöntem kullandığını gördüm. Kod şöyle görünecektir:

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

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

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

Bu işin nasıl yapılacağını bilen var mı? Yazman gerektiğini duydum

Object.prototype.extend = function(...);

Ama bu sistemi nasıl çalıştıracağımı bilmiyorum. Mümkün değilse, lütfen bana bir nesneyi uzatan başka bir alternatif gösterin.


geri dönüş; ama bu yüzden soruyorum :)
Wituz

2
MDN bu güzel öğretici geçmesini öneririm: - developer.mozilla.org/en/…
Pranav

Bu güzel dokümanları okuduktan sonra hala bir extendişlev merak ediyorsanız , burada bir örnek oluşturdum: jsfiddle.net/k9LRd
Codrin

2
Ayrıca 'Java'dan JavaScript'e dönüştürme' ve 'Java ile benzer sözdizimine sahip yeni bir dil, Javascript, öğrenme' olarak düşünmemeyi öneririm
Toni Leigh

Yanıtlar:


195

Kişinin prototip nesnesinden 'miras almak' istersiniz:

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.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

4
Bir sorum var: Yaparken Person()yapıcı nasıl çağrılıyor new Robot()? Yerine yapmanın bu temel sınıf yapıcısı çağırmalıdır geliyor bana this.name = name;içinde Robot()... yapıcısı
Alexis WILKE

21
@AlexisWilke: Evet, aramalısın Person.apply(this, arguments);. Bunun Robot.prototype = Object.create(Person.prototype);yerine kullanmak daha iyi olur new Person();.
Felix Kling

18
Felix tarafından belirtildiği gibi, 'Robot.prototype = Person.prototype;' 'Robot' tipinin kendi prototip örneğine sahip olmasını isterse kötü bir fikirdir. Robota özgü yeni işlevler eklemek de onu kişiye ekler.
James Wilkins

20
Bu örnek tamamen yanlış. Bunu yaparak Kişi prototipini değiştirmiş olursunuz. Bu kalıtım değil ve Person sınıfına büyük bir karışıklık verme riskiniz var. Object.create () kullanılmasını öneren yanıta bakın. Bir şeyler yapmanın doğru yolu budur.
nicolas-van

6
@osahyoun bu cevap google aramada yüksek bir sıralamaya sahip. Gerçekten kodu düzeltmenizi ve burada diğer yorumlar tarafından önerilen prototip zincirini düzeltmenizi öneririm.
raphaëλ

103

"Yeni" anahtar kelimesi olmayan dünya.

Ve Object.create () ile daha basit "düzyazı benzeri" sözdizimi.

* Bu örnek ES6 sınıfları için güncellenmiştir.

Öncelikle, Javascript'in prototip bir dil olduğunu unutmayın . Sınıf temelli değildir. Bu nedenle, prototip biçiminde yazmak gerçek doğasını ortaya çıkarır ve çok basit, nesir benzeri ve güçlü olabilir.

TLDR;

const Person = { name: 'Anonymous' } // person has a name

const jack = Object.create(Person)   // jack is a person
jack.name = 'Jack'                   // and has a name 'Jack'

Hayır, kuruculara ihtiyacınız yok, newsomutlaşma yok ( neden kullanmamanız gerektiğini okuyunnew ), hayır super, komik komik değil __construct. Siz sadece Nesneleri yaratıp sonra genişletir ya da dönüştürürsünüz.

( Alıcıları ve ayarlayıcıları biliyorsanız, bu kalıbın size Javascript'in başlangıçta amaçladığı şekilde nasıl ücretsiz alıcılar ve ayarlayıcılar verdiğini ve ne kadar güçlü olduklarını görmek için "Daha fazla okuma" bölümüne bakın .)

Düzyazı benzeri sözdizimi: Temel protokol

const Person = {

   //attributes
   firstName : 'Anonymous', 
   lastName: 'Anonymous',
   birthYear  : 0,
   type : 'human',

   //methods
   name() { return this.firstName + ' ' + this.lastName },
   greet() {
       console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' )
   },
   age() {
      // age is a function of birth time.
   }
}

const person = Object.create(Person). // that's it!

Bir bakışta, çok okunabilir görünüyor.

Uzantısı, Person

* Doğru şartlar prototypesve onların descendants. Gerek yok classes, gerek yok instances.

const Skywalker = Object.create(Person)
Skywalker.lastName = 'Skywalker'

const anakin = Object.create(Skywalker)
anakin.firstName = 'Anakin'
anakin.birthYear = '442 BBY'
anakin.gender = 'male' // you can attach new properties.
anakin.greet() // 'Hi, my name is Anakin Skywalker and I am a human.'

Person.isPrototypeOf(Skywalker) // outputs true
Person.isPrototypeOf(anakin) // outputs true
Skywalker.isPrototypeOf(anakin) // outputs true

A oluşturmanın "varsayılan" bir yolunu sağlamanın bir yolu, descendantbir #createyöntem eklemektir :

Skywalker.create = function(firstName, gender, birthYear) {

    let skywalker = Object.create(Skywalker)

    Object.assign(skywalker, {
        firstName,
        birthYear,
        gender,
        lastName: 'Skywalker',
        type: 'human'
    })

    return skywalker
}

const anakin = Skywalker.create('Anakin', 'male', '442 BBY')

Aşağıdaki yollar daha düşük okunabilirliğe sahiptir:

"Klasik" eşdeğeriyle karşılaştırın:

function Person (firstName, lastName, birthYear, type) {
    this.firstName = firstName 
    this.lastName = lastName
    this.birthYear = birthYear
    this.type = type
}

// attaching methods
Person.prototype.name = function() { return firstName + ' ' + lastName }
Person.prototype.greet = function() { ... }
Person.prototype.age = function() { ... }

function Skywalker(firstName, birthYear) {
    Person.apply(this, [firstName, 'Skywalker', birthYear, 'human'])
}

// confusing re-pointing...
Skywalker.prototype = Person.prototype
Skywalker.prototype.constructor = Skywalker

const anakin = new Skywalker('Anakin', '442 BBY')

Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns false!

"Klasik" stil kullanılarak kod okunabilirliği iyi değildir.

ES6 Sınıfları

Kuşkusuz, bu sorunların bazıları ES6 sınıfları tarafından ortadan kaldırılıyor, ancak yine de:

class Person {
    constructor(firstName, lastName, birthYear, type) {
        this.firstName = firstName 
        this.lastName = lastName
        this.birthYear = birthYear
        this.type = type
    }
    name() { return this.firstName + ' ' + this.lastName }
    greet() { console.log('Hi, my name is ' + this.name() + ' and I am a ' + this.type + '.' ) }
}

class Skywalker extends Person {
    constructor(firstName, birthYear) {
        super(firstName, 'Skywalker', birthYear, 'human')
    }
}

const anakin = new Skywalker('Anakin', '442 BBY')

// prototype chain inheritance checking is partially fixed.
Person.isPrototypeOf(anakin) // returns false!
Skywalker.isPrototypeOf(anakin) // returns true

Temel prototipin dallanması

// create a `Robot` prototype by extending the `Person` prototype:
const Robot = Object.create(Person)
Robot.type = 'robot'
Robot.variant = '' // add properties for Robot prototype

İçin benzersiz yöntemler ekleyin Robot

// Robots speak in binaries, so we need a different greet function:
Robot.machineGreet = function() { /*some function to convert strings to binary */ }

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

Miras kontrolü

Person.isPrototypeOf(Robot) // outputs true
Robot.isPrototypeOf(Skywalker) // outputs false

Zaten ihtiyacınız olan her şeye sahipsiniz! Yapıcı yok, örnekleme yok. Temiz, açık nesir.

daha fazla okuma

Yazılabilirlik, Yapılandırılabilirlik ve Serbest Mektuplar ve Ayarlayıcılar!

Ücretsiz alıcılar ve ayarlayıcılar veya ekstra yapılandırma için Object.create () öğesinin ikinci argümanını aka özellikObject kullanabilirsiniz. Ayrıca # Object.defineProperty ve # Object.defineProperties dosyalarında da mevcuttur .

Bunun ne kadar güçlü olduğunu göstermek için, hepimizin Robotkesinlikle metalden (aracılığıyla writable: false) yapılmasını istediğimizi ve powerConsumptiondeğerleri (alıcılar ve ayarlayıcılar aracılığıyla ) standartlaştırdığımızı varsayalım .

const Robot = Object.create(Person, {
    // define your property attributes
    madeOf: { 
        value: "metal",
        writable: false,
        configurable: false,
        enumerable: true
    },
    // getters and setters, how javascript had (naturally) intended.
    powerConsumption: {
        get() { return this._powerConsumption },
        set(value) { 
            if (value.indexOf('MWh')) return this._powerConsumption = value.replace('M', ',000k') 
            this._powerConsumption = value
            throw new Error('Power consumption format not recognised.')
        }  
    }
})

const newRobot = Object.create(Robot)
newRobot.powerConsumption = '5MWh'
console.log(newRobot.powerConsumption) // outputs 5,000kWh

Ve tüm prototipleri başka bir şey Robotolamaz madeOfçünkü writable: false.

const polymerRobot = Object.create(Robot)

polymerRobot.madeOf = 'polymer'

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

Mixins (# Object.assign kullanarak) - Anakin Skywalker

Bunun nereye gittiğini hissedebiliyor musun ...?

const darthVader = Object.create(anakin)
// for brevity, property assignments are skipped because you get the point by now.

Object.assign(darthVader, Robot)

Darth Vader şu yöntemleri alır Robot:

darthVader.greet() // inherited from `Person`, outputs "Hi, my name is Darth Vader..."
darthVader.machineGreet() // inherited from `Robot`, outputs 001010011010...

Diğer garip şeylerle birlikte:

console.log(darthVader.type) // outputs robot.
Robot.isPrototypeOf(darthVader) // returns false.
Person.isPrototypeOf(darthVader) // returns true.

Darth Vader'ın insan mı yoksa makine mi olduğu gerçekten özneldir:

"O şimdi insandan daha fazla makine, bükülmüş ve kötü." - Obi-Wan Kenobi

"İçinde iyi olduğunu biliyorum." - Luke Skywalker

Ekstra - # Object.assign ile biraz daha kısa sözdizimi

Büyük olasılıkla, bu model sözdizimini kısaltır. Ancak ES6 # Object.assign biraz daha kısaltabilir ( Çoklu dolgunun eski tarayıcılarda kullanılması için ES6'da MDN'ye bakın ).

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

//you can do this
const Robot = Object.create(Person)
Object.assign(Robot, {
    name: "Robot",
    madeOf: "metal"
    // for brevity, you can imagine a long list will save more code.
})

8
yapıcı işlevini kullanmadığından emin olun.
nsmarks

1
"klasik eğitimli" programcılar, bununla ne demek istiyorsun?
Petra

1
Klasik bir OOP zihniyetinden geliyorum ve bu cevap bana çok yardımcı oldu. Kod üzerinde iki soru: 1) Bugünün ES2015 yöntemi Object.assign(Robot, {a:1}için iyi bir alternatif extend()mi? 2) greet()Aynı metni döndürecek şekilde, ancak "selam geçersiz kılma" ifadesi eklenmiş olarak yöntemi nasıl geçersiz kılabilirim?
Barry Staes

2
1) #Object.assigniyi bir alternatif gibi görünüyor. Ancak tarayıcı desteği daha düşük atm'dir. 2) __proto__Prototipin karşılama işlevine erişmek için nesnenin özelliğini kullanacaksınız . daha sonra callee'nin kapsamı geçerek prototip selamlama işlevini çağırırsınız. bu durumda işlev bir konsol günlüğüdür, bu nedenle "eklemek" mümkün değildir. Ama bu örnekle, sapmayı elde ettiğinizi düşünüyorum. skywalker.greet = function() { this.__proto__.greet.call(this); console.log('a greet override'); }
Calvintwr

1
ECMAScript Dil Spesifikasyonu koruyucularla yapılması gereken bir tartışma. Genel olarak katılıyorum, ama sahip olduğum şeyle çalışmam gerekiyor.

51

Henüz bir yol bulamadıysanız, Object.prototypeaşağıda gösterildiği gibi bir genişletme işlevi eklemek için JavaScript nesnelerinin ilişkisel özelliğini kullanın .

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

Daha sonra bu işlevi aşağıda gösterildiği gibi kullanabilirsiniz.

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

o.extend(x);

18
'Ana' sınıftaki nesneleri / dizileri kullanırken, bunun 'child' sınıfındaki orijinal nesneye işaretçiler oluşturacağına dikkat edin. Ayrıntılı olarak açıklamak için: Üst sınıfınızda bir nesne veya dizi varsa, bunu bu temelde uzanan bir alt sınıfta değiştirmek, aslında aynı temel sınıfta uzanan tüm alt sınıflar için bu nesneyi değiştirir.
Harold

Harold, bu gerçeği vurguladığınız için teşekkürler. İşlevi kullanan kişi, nesneleri / dizileri kontrol eden ve bunların kopyalarını oluşturan bir koşulu dahil etmek için önemlidir.
tomilay

30

Farklı yaklaşım: Object.create

@Osahyoun cevabına göre, aşağıdakileri Kişinin prototip nesnesinden 'miras' almanın daha iyi ve etkili bir yolu olarak görüyorum:

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;

Yeni örnekler oluşturun:

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

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

Şimdi, Object.create kullanarak :

Person.prototype.constructor !== Robot

Ayrıca MDN belgelerine de bakın.


2
@GaretClaborn'un düzgün çalıştığını söylemek istiyorum, ancak nameparametreyi aşağıdaki gibi ana yapıcıya geçirmiyorsunuz : jsfiddle.net/3brm0a7a/3 (fark # 8 satırındadır)
xPheRe

1
@xPheRe Ah Anlıyorum, teşekkürler. Cevabı bu değişikliği yansıtacak şekilde düzenledim
Garet Claborn

1
@xPheRe, sanırım bu çözümü eklediğimde bir noktayı kanıtlamaya odaklandım. Teşekkürler.
Lior Elrom

1
Güzel cevap +1, ECMAScript 6'ya bir göz atabilirsiniz. Anahtar kelimeler sınıfı ve genişletme kullanılabilir: developer.mozilla.org/en-US/docs/Web/JavaScript/…
Benjamin Poignant

26

ES6'da forma operatörünü

var mergedObj = { ...Obj1, ...Obj2 };

Object.assign () öğesinin ayarlayıcıları tetiklediğini, ancak yayılım sözdiziminin tetiklemediğini unutmayın.

Daha fazla bilgi için bkz. Bağlantı, MDN -Spread Sözdizimi


Eski Cevap:

ES6'daObject.assign özellik değerlerini kopyalamak için vardır . {}Hedef nesneyi değiştirmek istemiyorsanız, ilk parametre olarak kullanın (ilk parametre geçer).

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

Daha fazla ayrıntı için bkz. MDN - Object.assign ()

İhtiyacınız olursa ES5 için bir Polyfill olması durumunda , bağlantı da bunu sunar. :)


18

Ve bir yıl sonra, size güzel bir cevap daha olduğunu söyleyebilirim.

Nesneleri / sınıfları genişletmek için prototiplemenin çalışma şeklinden hoşlanmıyorsanız, şuna bir bakın: https://github.com/haroldiedema/joii

Hızlı örnek olasılık kodu (ve daha fazlası):

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"

Peki, 2 yıl bitene kadar hala 2 ayım var: P Her iki durumda da, JOII 3.0 serbest bırakmak üzeredir :)
Harold

1
Bunu 3 yıl sonra yap.

İlginç bir kavram, ancak sözdizimi gerçek çirkin görünüyor. ES6 derslerinin istikrarlı hale gelmesini beklemeniz daha iyi olur
sleepycal

Tamamen katılıyorum @sleepycal. Ancak maalesef, tüm büyük / ortak tarayıcıların bunu uygulaması en az 5 yıl daha sürecek. O zamana kadar, bunu yapmak zorunda kalacak ...
Harold

12

Hala basit ve en iyi yaklaşım için mücadele eden insanlar, Spread Syntaxnesneyi genişletmek için kullanabilirsiniz .

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);

Not: Mülkün en sağdaki önceliğe sahip olacağını unutmayın. Bu örnekte, person2sağ tarafta, içinde RobonewObj ismi olacak .



6

Mozilla, ECMAScript 6.0'dan uzanan nesneyi 'duyurdu':

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

NOT: Bu, ECMAScript 6 (Uyum) teklifinin bir parçası olan deneysel bir teknolojidir.

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;     } 
}

Bu teknoloji Gecko'da (Google Chrome / Firefox) mevcuttur - 03/2015 gece yapıları.


4

Projenin çoğunda nesne genişletme konusunda bazı uygulamalar vardır: alt çizgi, jquery, lodash: genişlet .

ECMAscript 6'nın bir parçası olan saf javascript uygulaması da var: Object.assign : https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign


“Saf javascript uygulaması”, yerel olarak uygulanabilecek, ortam tarafından sağlanan bir işleve değil, yalnızca JavaScript ile uygulanan bir şeye işaret etmiyor mu?
binki

1
@binki, yerel javascript uygulaması demekti - ECMAScript 2015 (ES6) standardının bir parçası
Cezary Daniel Nowak

2
Function.prototype.extends=function(ParentClass) {
    this.prototype = new ParentClass();
    this.prototype.constructor = this;
}

Sonra:

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

01/2017 Güncellemesi:

Javascript artık extendsES6'dan beri anahtar kelimeyi desteklediğinden lütfen 2015 yanıtımı yoksay (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

1
Kurucunun new ParentClass()üzerine yazmadan önce arayarak üst kurucuyu zaten yürüttünüz. Bana sorarsan bu doğru davranış olduğunu sanmıyorum ...
Harold

1

Özet:

Javascript prototip palet mirası denilen bir mekanizma kullanır . Prototypal mirası, bir nesne üzerindeki bir özelliği ararken kullanılır. Javascript'teki özellikleri genişletirken, bu özellikleri gerçek bir nesneden devralırız. Aşağıdaki şekilde çalışır:

  1. Bir nesne özelliği istendiğinde, (örneğin myObj.fooveya myObj['foo']) JS motoru ilk önce o özelliği nesnenin kendisinde arar
  2. Bu özellik nesnenin kendisinde bulunmadığında , prototip nesnesine prototip zincirine bakacaktır. Bu özellik de burada bulunmazsa, mülk bulunana kadar prototip zincirine tırmanmaya devam eder. Özellik bulunmazsa, bir referans hatası verir.

Javascript'teki bir nesneden genişletmek istediğimizde bu nesneyi prototip zincirine bağlayabiliriz. Bunu başarmanın çeşitli yolları vardır, yaygın olarak kullanılan 2 yöntemi açıklayacağım.

Örnekler:

1. Object.create()

Object.create()bir nesneyi bağımsız değişken olarak alan ve yeni bir nesne oluşturan bir işlevdir. Bağımsız değişken olarak iletilen nesne, yeni oluşturulan nesnenin prototipi olacaktır. Örneğin:

// 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. Prototip özelliğini açıkça ayarlama

Yapıcı işlevlerini kullanarak nesne oluştururken prototip nesne özelliğine add özellikleri ayarlayabiliriz. newAnahtar sözcüğü kullanılırken bir yapıcı işlevinden oluşturulan nesnelerin prototipleri yapıcı işlevinin prototipine ayarlanır. Örneğin:

// 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));


0

Bunu kullanarak şunları yapabilirsiniz:

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: Bir nesne this[i] != nullolduğundan beri kontrol ettimnull

Sonra şöyle kullanın:

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

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

defaults.extend(options);

Bu iyi sonuç:

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

0

İNDİRMEK İÇİN LÜTFEN NEDEN EKLE

  • Genişletmek için herhangi bir harici kitaplık kullanmaya gerek yok

  • JavaScript'te her şey bir nesnedir (üç ilkel veri türü hariç ve hatta gerektiğinde otomatik olarak nesnelerle sarılır). Ayrıca, tüm nesneler değiştirilebilir.

JavaScript'te Sınıf Personeli

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);

Belirli bir örneği / nesneyi değiştirme .

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

Sınıfı değiştirme

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

Veya basitçe şunu söyleyin: JSON ve OBJECT'i genişletin her ikisi de aynı

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

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

ross harmes sayesinde, dustin diaz


-1

Bu, özelliklerinizin genişletilmesini, iletilen nesneyi değiştirmeden nesne parametresi prototipleriyle yeni bir Nesne oluşturmasını sağlar.

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();
}

Ancak, Nesnenizi parametrelerini değiştirmeden genişletmek istiyorsanız, nesnenize extProperty ekleyebilirsiniz.

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
        }
    }

-2

Prototip oluşturma iyi bir yoldur, ancak prototip bazen oldukça tehlikelidir ve hatalara yol açabilir. Bunu, Ember.js'nin Ember.Object.extend ve Ember.Object.reopen'e yaptığı gibi bir temel nesneye kapsüllemeyi tercih ederim. Kullanımı çok daha güvenli.

Ember.Object'in kullandığı şeye benzer bir şey nasıl kuracağınıza dair bir özgeçmiş oluşturdum.

Bağlantı şu şekildedir: https://gist.github.com/WebCloud/cbfe2d848c80d4b9e9bd


9
Prototyping is a nice way, but prototype is quite dangerous sometimes and can lead to bugs.Bununla ne demek istiyorsun? Prototip zincirini JavaScript'te kullanmak hatalara yol açabilir mi? Java üzerinde sınıf kullanmanın hatalara yol açabileceğini ve kesinlikle bir anlam ifade edemeyeceğini söylemek gibi bir şey.
HMR

@HMR, ortam tarafından sağlanan nesne prototiplerinin genişletilmesinin gelecekteki temel bir JavaScript dil özelliğiyle çakışabilecek kırılgan kodlarla sonuçlandığını söylüyor. ObjectPrototipini genişleterek her şeye yararlı bir yardımcı program işlevi eklerseniz , işleviniz gelecekteki bir JavaScript işleviyle aynı ada sahip olabilir ve gelecekte çalıştırıldığında kodunuzun patlamasına neden olabilir. Örneğin, örneklere bir repeat()işlev ekleyip işlev olarak Objectçağırdığınızı Stringve ardından JavaScript çalışma zamanınızın ES6 olarak güncellendiğini varsayalım?
binki

@binki Girişiniz için teşekkür ederiz. "Sahip olmadığınız" sınıfların prototipini değiştirmek ve böylelikle enkapsülasyon referansını kırmaktan bahsediyorsunuz: developer.mozilla.org/en/docs/Web/JavaScript/… JS, API'nizin uygulama üyelerini açığa çıkarması için özel değişkenlere sahip değil , bu genellikle sözleşmeyle çözülür (üye adını alt çizgiyle başla). Operasyonun sahip olduğu ana sorun olup olmadığından veya sözdiziminin kafa karıştırıcı olduğundan ve birçok insanın bunu anlamadığından emin değilim.
HMR

@HMR, yanlış olabilir, ama bence “ama prototip oldukça tehlikelidir” anlamına gelir rezil prototip çerçevesinde kötüye olabilir prototypedil özelliği .
binki

Prototip oluşturma tehlikelidir, çünkü oluşturmadığınız nesneleri kullanıyorsanız, yan etkilerin prototip olarak kullanacağını her zaman bilemezsiniz. Örneğin bu kemana
Arkain
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.