11

JavaScript では、「プロトタイプ」という単語をいつ使用するか、「プロトタイプ」という単語を使用せずに単純な「ドット」表記を使用するかを理解できません。誰かがこれらのコード ブロックを見て、どちらを使用するかを理解するのを手伝ってくれませんか?

「プロトタイプ」で:

function employee(name,jobtitle)
{
  this.name=name;
  this.jobtitle=jobtitle;
}

var fred=new employee("Fred Flintstone","Caveman");
employee.prototype.salary=null;
fred.salary=20000;
console.log(fred.salary);

「プロトタイプ」なし:

function employee(name,jobtitle,salary)
{
  this.name=name;
  this.jobtitle=jobtitle;
  this.salary=salary;
}

var fred=new employee("Fred Flintstone","Caveman", 20000);
console.log(fred.salary);
4

7 に答える 7

8

JavaScript オブジェクトには、別のオブジェクトへのポインタであるプロパティがあります。このポインターは、オブジェクトのプロトタイプです。デフォルトでは、オブジェクト インスタンスは同じプロトタイプを共有します。

function Employee(name){
  this.name = name;
}

Employee.prototype.company = "IBM";

Employee.prototype.who = function(){
  console.log("My name is", this.name, "I work for", this.company);
}

var bob = new Employee('Bob');
var jim = new Employee('Jim');

// bob and jim are seperate objects, but each is linked to the same 'prototype' object.

jim.who(); // jim doesn't have a property called 'who', so it falls back to it's 'prototype', where who exists
// My name is Jim I work for IBM

bob.who();
// My name is Bob I work for IBM

// Bob leaves IBM for Microsoft
bob.company = "Microsoft"; // bob now has a property called 'company'. The value of which is 'Microsoft', which overrides bob's prototype property of the same name.

bob.who();
// My name is Bob I work for Microsoft

Employee.prototype.company = 'Facebook';

jim.who(); 
// My name is Jim I work for Facebook

bob.who(); // Bob is not affected by the change.
// My name is Bob I work for Microsoft

delete bob.company;

bob.who(); // bob no longer has it's own property 'company', so like jim, it drops down to the prototype object.
// My name is Bob I work for Facebook
于 2012-05-03T12:21:45.817 に答える
8

JS と継承に関する問題は複雑かもしれませんが、あなたの質問に対する答えは比較的単純です。次のコードを検討してください。

 function Klass() { }
 var obj1 = new Klass();
 var obj2 = new Klass();

にプロパティを追加するとobj1、そのプロパティは にのみ存在しobj1ます。同様にobj2

プロパティを に追加するとKlass、そのプロパティも同様に Klass (関数オブジェクト) にのみ存在します。obj1影響はありませんobj2

しかし、プロパティを に追加するとKlass.prototype、そのプロパティは と の両方に存在し、obj1obj2介して作成される将来のオブジェクトにも存在しますnew Klass。その後、プロトタイプのプロパティの値を変更すると、変更された値がすべてのオブジェクトに表示されます。

関数の本体内にコードKlassを追加して、プロパティを追加できますthis。これにより、将来のすべてのKlassオブジェクトがそれらのプロパティを取得します。ただし、各オブジェクトには独自のコピーがあり、特にプロパティがメソッドである場合、メモリの観点から合計される可能性があり、これらのコピーは の本体に対する将来の変更の影響を受けませんKlass

于 2012-05-03T13:22:23.223 に答える
2

ES5 のおかげで、もうObject.create面倒なことをする必要がほとんどなくなりました。.prototype

したがって、@Gerry の例を取り上げると、次のようになります。

var Mammal = {
    walk: function() {}
};

var Dog = Object.create(Mammal, {
    bark: {
        value: function() {}
    }
}); // create a new object which [[prototype]] refers to Mammal

Dog.walk();
Dog.bark();
于 2012-05-03T11:59:48.850 に答える
1

オブジェクトを理解するのprototypeは少し難しいです。ただし、OOP JavaScriptに関するこの記事は、いくつかの光を当てるのに役立ちます。

簡単に言うと、prototypeオブジェクトは「受信者」オブジェクトの青写真を提供します。必要なのは、受信者のprototypeプロパティを青写真オブジェクトに向けるだけです。プロトタイプブループリントオブジェクトの受信者は好きなだけ持つことができることに注意してください(したがって、CarとTrainは両方とも共通のVehicleプロトタイプオブジェクトを指すことができます)。

プロトタイプオブジェクトでプロパティと関数の両方を自由に定義できます。これにより、すべての受信者オブジェクトが使用できるようになります。例:

var vehiclePrototype = {
    // A property which will be supplied to the recipient
    cost: 0,

    // A method which will be supplied the recipient
    move: function () { 
        // Your prototype can refer to 'this' still.
        console.log("Moving " + this.name);
    };
}

これで、 :Carを使用するを作成できます。vechiclePrototype

// Factory method for creating new car instances.
function createCar(name) {
    // Define the Car's constructor function
    function Car(name) {
        this.name = name;
    }

    // Point the car's prototype at the vechiclePrototype object
    Car.prototype = vechiclePrototype;

    // Return a new Car instance 
    return new Car(name);
}

// Create a car instance and make use of the Prototype's methods and properties
var mustang = createCar(mustang);
mustang.cost = 5000;
mustang.move();

同様の方法で、新しいTrainオブジェクトを作成できます。

function createTrain(whilstleSound) {
    // Define the Train's constructor function
    function Train(name) {
        this.whilstleSound = whilstleSound;
    }

    // Point the train's prototype at the vechiclePrototype object
    Train.prototype = vechiclePrototype;

    // Return a new Train instance 
    return new Train(name);
}

var ic125 = new Train("pooop pooop");
ic125.move();

プロトタイプ継承を使用して両方のすべてのインスタンスを使用し、(同じ関数の複数のインスタンスを作成する代わりに)まったく同じ関数CarTrain共有することの大きな利点の1つは、これらのオブジェクトのインスタンスが多数ある場合に大幅なメモリ節約になります。move

于 2012-05-03T12:19:35.987 に答える
1

無視してくださいnew、無視.prototypeしてください。それらは単に混乱を招く概念です。本当にプロトタイプの継承を使用したいObject.createが、ほとんどの場合、継承は完全にやり過ぎです。(プロトタイプの継承は、最適化手法としてのみ使用する必要があります)。

クラスを構築するときは、オブジェクトを作成して拡張するだけです。

var Walker = {
    walk: function() {}
}

var Eater = {
    eat: function () {}
}

var Dog = extend({}, Eater, Walker, {
    bark: function () {},
    sniffBehind: function () {}
})

function dog(dogName) {
    return extend({}, Dog, {
        name: dogName
    })
}

var steveTheDog = dog("steve")
console.log(steveTheDog.name === "steve")

任意のアリティ拡張関数 、 、 などを使用_.extendjQuery.extendますpd.extend

pdは次のように実装extendします

function extend(target) {
    [].slice.call(arguments, 1).forEach(function(source) {
        Object.getOwnPropertyNames(source).forEach(function (name) {
            target[name] = source[name]
        })
    })
    return target
}
于 2012-05-03T12:57:45.870 に答える
0

プロトタイプを使用すると、コンストラクター関数内のロジックをオブジェクトを定義するプロパティおよびメソッドから分離しているため、「よりクリーンな」方法で拡張できます。

var Mammal = function() { ... };
Mammal.prototype = {
  walk: function() { ... }
};

var Dog = function() { ... };

for (var prop in Mammal.prototype) {
  Dog.prototype[prop] = Mammal.prototype[prop];
}

Dog.prototype.bark = function() { ... };

ただし、プロトタイプのない上記は次のようになります。

var Mammal = function() {
  this.walk = function() { ... };
};

var Dog = function() {
  Mammal.apply(this);
  this.bark = function() { ... };
};

ただし、オブジェクトを拡張するこの方法は、Underscore.js などの最新の JavaScript ライブラリでは無関係になり、jQuery などの助けを借りてよりきれいに記述できます。

于 2012-05-03T11:55:06.557 に答える
0

この単語prototypeを使用して、アプリケーション全体で特定の型 (配列、関数、カスタム型の数) の機能を定義できます。

たとえば、すべての配列をプロパティで拡張できますsum

const arrayPrototype = Array.prototype
Object.defineProperty(arrayPrototype, 'sum', { 
   get() { return this.reduce((a,b) => a + b, 0) }
})

コードのチャンクを実行すると、すべての配列に次のプロパティがあります。

console.log([1,3,-1,10].sum) // prints 13
于 2021-12-15T13:01:16.077 に答える