Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
什么时候使用这个词;原型;在javascript中将新属性添加到对象中?_Javascript_Object_Prototype - Fatal编程技术网

什么时候使用这个词;原型;在javascript中将新属性添加到对象中?

什么时候使用这个词;原型;在javascript中将新属性添加到对象中?,javascript,object,prototype,Javascript,Object,Prototype,我不明白在JavaScript中何时使用“prototype”一词,何时使用简单的“dot”符号而不使用“prototype”。有人能看一下这些代码块并帮助我理解您何时想使用其中一个而不是另一个吗 带有“原型”: 无原型: 使用prototype,您可以以“更干净”的方式进行扩展,因为您将构造函数内的逻辑与定义对象的属性和方法分离 var Mammal = function() { ... }; Mammal.prototype = { walk: function() { ... } };

我不明白在JavaScript中何时使用“prototype”一词,何时使用简单的“dot”符号而不使用“prototype”。有人能看一下这些代码块并帮助我理解您何时想使用其中一个而不是另一个吗

带有“原型”:

原型:


使用prototype,您可以以“更干净”的方式进行扩展,因为您将构造函数内的逻辑与定义对象的属性和方法分离

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

然而,像underline.js这样的现代JavaScript库使这种扩展对象的方式变得无关紧要,或者在例如jQuery的帮助下也可以编写得更干净。

ES5的
对象。创建
几乎不再需要与
.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();

原型
对象有点难以理解;然而,这有助于阐明一些问题

简而言之,
prototype
对象为“接收者”对象提供了一个蓝图-您所要做的就是将接收者的
prototype
属性指向blueprint对象。请注意,您可以有任意多个原型蓝图对象的接收者(因此Car和Train都可以指向一个公共的车辆原型对象)

您可以在原型对象中自由定义属性和函数,任何收件人对象都可以使用该原型对象,例如:

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);
    };
}
现在,您可以创建一辆
汽车
,它使用
车辆原型

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

使用原型继承的最大优点之一是
Car
Train
的所有实例共享完全相同的
move
函数(而不是创建同一函数的多个实例)如果存在这些对象的多个实例,则会显著节省内存。

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

忽略
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")
使用您想要的任意算术扩展函数,
\uuu.extend
jQuery.extend
,等等

实现
扩展
,如下所示

function extend(target) {
    [].slice.call(arguments, 1).forEach(function(source) {
        Object.getOwnPropertyNames(source).forEach(function (name) {
            target[name] = source[name]
        })
    })
    return target
}

关于JS和继承的问题可能很复杂,但您的问题的答案相对简单。考虑这个代码:

 function Klass() { }
 var obj1 = new Klass();
 var obj2 = new Klass();
现在,如果将属性添加到
obj1
,则该属性仅存在于
obj1
上。同样地,
obj2

如果将属性添加到
Klass
,则该属性同样仅存在于Klass(函数对象)上。它根本不影响
obj1
obj2

但是,如果您将属性添加到
Klass.prototype
,则该属性将同时出现在
obj1
obj2
上,以及通过
新建Klass
创建的任何未来对象上。如果随后更改原型上属性的值,则更改后的值将是您在所有这些对象上看到的值


您可以在
Klass
函数的主体中添加代码,以向
添加属性;这将导致任何未来的
Klass
对象获得这些属性。但是每个对象都会有自己的副本-可以在内存方面进行累加,特别是当属性是方法时-并且这些副本不会受到
Klass

主体的未来更改的影响。您的示例将
树皮
方法添加到
哺乳动物。原型
,因此,所有的
哺乳动物
实例都能吠叫,而不是所有的
(我假设你打算只让狗能吠叫)。我对构造器实际上是什么也有点困惑。这就是构造函数,
var=function(){…}?如果是这样的话,那为什么不叫“object”?@Timperson构造函数只是一个普通的JavaScript函数,唯一的区别是它是如何被调用的,即使用“new”关键字。这就引出了下一个问题,什么时候使用“new”这个词与生成函数时不同?如果成员是方法,则向构造函数的
prototype
属性添加成员是有意义的-您只需将其放入原型中,所有实例都将继承它们,而不是在每个实例上定义通用方法。如果我可以建议您,我可能会认为@mark Reed的答案是正确的,因为他比其他人解释得更好。也许还是有可能以某种方式改变正确的答案。但这只是一个建议。谢谢。嗨,jAndy,这个新语法背后的逻辑是什么?@Timperson:实际上,你可以从没有构造函数的对象继承,如上图所示。您仍然可以将构造函数与
对象结合使用。当然,创建
可以获得更高级、更复杂的继承。在一般情况下,
Object.create
将创建一个新对象,并指向作为第一个参数传入的对象的
.prototype
,第二个参数是可以创建其他“自己”属性的对象。请参见
var Dog=extend({},哺乳动物,{bark:function(){}})
@Raynos:我真的很想看到另一个关于纯OC概念的答案。@jAndy这不是真正的OC,只是混合。谢谢Raynos,所以我需要使用
.\extend
$.extend