JavaScript:为什么Object.hasOwnProperty方法的行为是这样的?

JavaScript:为什么Object.hasOwnProperty方法的行为是这样的?,javascript,inheritance,hasownproperty,Javascript,Inheritance,Hasownproperty,我的理解是Object.hasOwnProperty方法检查对象是否有自己的属性名,即非继承属性。这意味着,每当属性a被调用时,函数应该返回false。不存在,或b。如果是遗传的 如果我错了,请纠正我,但除非这不使用经典继承,否则在下面的代码中,bar不是从Foo继承吗?当propname属性是继承属性时,为什么hasOwnProperty方法返回true?我在这里做错了什么 另外,如何在Foo对象上使用hasOwnProperty?这里的代码在检查Foo对象时返回false function

我的理解是Object.hasOwnProperty方法检查对象是否有自己的属性名,即非继承属性。这意味着,每当属性a被调用时,函数应该返回false。不存在,或b。如果是遗传的

如果我错了,请纠正我,但除非这不使用经典继承,否则在下面的代码中,bar不是从Foo继承吗?当propname属性是继承属性时,为什么hasOwnProperty方法返回true?我在这里做错了什么

另外,如何在Foo对象上使用hasOwnProperty?这里的代码在检查Foo对象时返回false

function Foo() {
    this.propname = 'test';
}

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
不,propname实际上是在new创建的Foo实例上设置的,基于Foo.prototype就是这样。构造器模式的另一个近似值更清楚地说明了发生了什么:

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";
不,propname实际上是在new创建的Foo实例上设置的,基于Foo.prototype就是这样。构造器模式的另一个近似值更清楚地说明了发生了什么:

var FooPrototype = {};
var bar = Object.create(FooPrototype);
bar.propname = "test";

这里的绊脚石是Javascript使用原型继承。你看到的其实根本不是继承

如果属性:

不存在。 存在,但仅在原型链上。 代码中的“类”根本与继承无关,它只是一个为对象设置某些属性的函数

该对象恰好是一个新空对象的实例,因为您使用new关键字调用了该函数,这可能是造成混淆的原因

想象一下,将函数重写为:

function foo() {
  var bar = {};
  bar.propname = 'test';
  return bar;
}

var baz = foo();
您希望baz.hasOwnProperty'propname'返回true吗?当然,因为我们明确定义了对象的属性

声明该属性的另一种方法是在Foo的原型上声明它

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false
再一次,这里发生的神奇的事情都取决于新的关键字。当您使用new调用函数时,函数会将其值指定为一个新对象,并将该对象的原型设置为与您正在调用的函数的原型相同

也许解释这一点最简单的方法是在bar上有一个hasOwnProperty方法,但是如果调用bar.hasOwnProperty'hasOwnProperty',它将返回false

这是因为hasOwnProperty方法位于原型链的最顶端,在Object.prototype上。Javascript中的每个对象都从这里继承,这就是为什么每个对象都有一个hasOwnProperty方法


关于为什么新技术使Javascript中的面向对象编程变得困难,有一个争论。

这里的绊脚石是Javascript使用原型继承。你看到的其实根本不是继承

如果属性:

不存在。 存在,但仅在原型链上。 代码中的“类”根本与继承无关,它只是一个为对象设置某些属性的函数

该对象恰好是一个新空对象的实例,因为您使用new关键字调用了该函数,这可能是造成混淆的原因

想象一下,将函数重写为:

function foo() {
  var bar = {};
  bar.propname = 'test';
  return bar;
}

var baz = foo();
您希望baz.hasOwnProperty'propname'返回true吗?当然,因为我们明确定义了对象的属性

声明该属性的另一种方法是在Foo的原型上声明它

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false
再一次,这里发生的神奇的事情都取决于新的关键字。当您使用new调用函数时,函数会将其值指定为一个新对象,并将该对象的原型设置为与您正在调用的函数的原型相同

也许解释这一点最简单的方法是在bar上有一个hasOwnProperty方法,但是如果调用bar.hasOwnProperty'hasOwnProperty',它将返回false

这是因为hasOwnProperty方法位于原型链的最顶端,在Object.prototype上。Javascript中的每个对象都从这里继承,这就是为什么每个对象都有一个hasOwnProperty方法


关于为什么新的Javascript使面向对象编程变得困难,有一个解释。

当您第一次编写Foo时,您只是定义了一个函数供以后使用

该条实例化了该函数,并基本上激活了其中的所有内容

用这些console.log检查一下这把小提琴

console.log(Foo)
console.log(bar)

当您第一次编写Foo时,您只需定义一个稍后使用的函数

该条实例化了该函数,并基本上激活了其中的所有内容

用这些console.log检查一下这把小提琴

console.log(Foo)
console.log(bar)

首先必须实例化Foo类的一个新对象

这个JS bin进一步说明了这一点:

正如您所看到的,构造函数仅在您
iate类Foo的一个新对象,在本例中是一个名为bar的变量。您正在调用函数Foo的hasOwnProperty。此函数不包含任何属性。

首先必须实例化Foo类的新对象

这个JS bin进一步说明了这一点:


正如您所见,只有在实例化类Foo的新对象时才会调用构造函数,在本例中,该对象是一个名为bar的变量。您正在调用函数Foo的hasOwnProperty。此函数不包含任何属性。

初始代码示例等效于:

function Foo() {
}

var bar = new Foo();
bar.propname = 'test';

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
这就是为什么bar.hasOwnProperty'propname'返回true该属性已在bar对象上显式设置,而Foo.hasOwnProperty'propname'返回false该属性根本未在Foo上设置,无论是在Foo对象本身还是原型上

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false
hasOwnProperty检查通常是这样使用的:

function Foo() {
    this.propname = 'test';
}
Foo.prototype.inheritedprop = 'test';

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(bar.hasOwnProperty('inheritedprop')); // returns false

初始代码示例相当于:

function Foo() {
}

var bar = new Foo();
bar.propname = 'test';

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(Foo.hasOwnProperty('propname')); // returns false
这就是为什么bar.hasOwnProperty'propname'返回true该属性已在bar对象上显式设置,而Foo.hasOwnProperty'propname'返回false该属性根本未在Foo上设置,无论是在Foo对象本身还是原型上

function Foo() {
  this.bar = 'baz';
}

Foo.prototype.propname = 'test';

var baz = new Foo();

baz.propname; // 'test'
baz.hasOwnProperty('propname'); // false
hasOwnProperty检查通常是这样使用的:

function Foo() {
    this.propname = 'test';
}
Foo.prototype.inheritedprop = 'test';

var bar = new Foo();

console.log(bar.hasOwnProperty('propname')); // returns true
console.log(bar.hasOwnProperty('inheritedprop')); // returns false


在第2行===栏中,此处未设置原型属性。通过设置Foo.prototype.propname=…Bar是Foo的实例,而不是后代来添加原型。@Douglas您能详细说明一下吗?为什么这需要一个原型呢?方法是检查属性…我在下面的回答中详细阐述了一点,但重点是“propname”不是继承的属性,原型需要涉及到某个地方才能有继承的属性。第2行的this===条,这里没有设置原型属性。通过设置Foo.prototype.propname=…Bar是Foo的实例,而不是后代来添加原型。@Douglas您能详细说明一下吗?为什么这需要一个原型呢?方法是检查属性…我在下面的回答中详细说明了一点,但重点是“propname”不是继承的属性,原型需要在某个地方参与才能继承属性。这可能就是为什么Addy Osmani在学习JavaScript设计模式时建议不要使用基本构造函数模式,而是使用原型模式的原因吗?他说构造函数模式使继承变得困难,但没有进一步详细说明。与Doug Crock不使用new的原因相同,尽管他不再使用Object.create。花点时间用另一种语言处理原型继承,我可以推荐Lua和Io,这对理解原型非常有帮助。在Javascript中,它们在感觉经典的语法下有些迷失。这可能就是为什么Addy Osmani在学习Javascript设计模式时建议不要使用基本构造函数模式,而是使用原型模式的原因吗?他说构造函数模式使继承变得困难,但没有进一步详细说明。与Doug Crock不使用new的原因相同,尽管他不再使用Object.create。花点时间用另一种语言处理原型继承,我可以推荐Lua和Io,这对理解原型非常有帮助。在Javascript中,它们在感觉很经典的语法下有些迷失。为什么属性实际上没有设置在Foo上?让我重写一下:当使用this关键字或原型时,为什么属性实际上没有设置在Foo上?在Foo上下文中,this关键字不应该设置属性吗?为什么这也不起作用:函数Foo{Foo.propname='test';}。我想这都是同一个问题。为什么它只在我编写Foo.propname='test'时起作用;函数之外?示例中有三个不同的对象:bar、Foo和Foo.prototype。hasOwnProperty方法检查特定对象的属性,因此,如果仅在三个对象中的一个对象上设置propname,则对于obj.hasOwnPropertypropname,只有该对象将返回true。函数Foo{Foo.propname='test';}将在Foo上设置propname,但只有在调用Foo时才会设置它。为什么Foo上没有实际设置属性?让我改写一下:为什么在使用this关键字或原型时,Foo上没有实际设置属性?在Foo上下文中,this关键字不应该设置属性吗?为什么这也不起作用:函数Foo{Foo.propname='test';}。我想这都是同一个问题。为什么它只在我编写Foo.propname='test'时起作用;函数之外?示例中有三个不同的对象:bar、Foo和Foo.prototype。hasOwnProperty方法检查特定对象的属性,因此,如果仅在三个对象中的一个对象上设置propname,则对于obj.hasOwnPropertypropname,只有该对象将返回true。函数Foo{Foo.propname='test';}将在Foo上设置propname,但它仅在调用Foo时设置。