JavaScript 原型对象 - 如何访问继承
JavaScript prototype-Object - how to access inheritance
目前,我试图理解Javascript原型对象。以下情况:
// new Person object
function Person () {
this.greeth = function() {
console.log("Good morning, " + this.name);
};
};
// add new function to Person.prototype for inheritance
Person.prototype.sayWeight = function() {
console.log(this.weight);
};
// create new friend object
var friend = {
forename: "Bill",
lastname: "Gates",
weight: 78,
sayhello: function() {
console.dir("Hello " + this.forename + ' ' + this.lastname);
}
};
// assign Person.prototype to friend.prototye (inheritance)
friend.prototype = Person;
console.dir(friend);
现在我的问题:我将人员对象分配给我的friend.prototype
。据我了解,"friend
"应该具有Person.prototype
的所有功能(即 sayWeight()
friend.prototype = Person;
的原因(。但我唯一可以调用的功能是friend.sayhello。在我的输出(console.dir(friend);
(中,我可以看到sayWeight()
函数,但是当我调用它时,我得到一个错误(TypeError: Object #<Object> has no method 'sayWeight'
(
你能解释一下这种行为吗?为什么我无法访问sayWeight()
功能?
====
=============================================================另一个问题:
function Person() {
this.name = "Bill Gates";
this.weight = 78;
this.sayHello = function() {
console.log("Hello " + this.name);
}
}
Person.prototype.sayWeight = function() {
console.log(this.weight);
}
var friend = new Person();
sayWeight
和sayHello
功能有什么区别?sayWeight
函数在 Person 的原型对象中 - 好的,但是在这种情况下,我从原型中有什么优势?
你能解释一下这种行为吗?为什么我无法访问 sayWeight(( 函数?
因为创建对象后无法更改对象的原型。您正在设置 prototype 属性,但 javascript 解释器使用的内部原型引用,即 __proto__
仍然是实际使用的引用,当前__proto__
引用的是 Object.prototype
。
如果您将此行friend.prototype = Person;
更改为此行friend.__proto__ = Person.prototype;
则一切正常。
如果您的浏览器支持 ES5,那么您可以使用 Object.create()
来创建继承自给定原型的对象,或者您可以使用 Javascript: The Good Parts 一书中采用的解决方法,并由 David Flanagan 在他的书中稍微扭曲: Javascript 权威指南:
// inherit() returns a newly created object that inherits properties from the
// prototype object p. It uses the ECMAScript 5 function Object.create() if
// it is defined, and otherwise falls back to an older technique.
function inherit(p) {
if (p == null) throw TypeError(); // p must be a non-null object
if (Object.create) // If Object.create() is defined...
return Object.create(p); // then just use it.
var t = typeof p; // Otherwise do some more type checking
if (t !== "object" && t !== "function") throw TypeError();
function f() {}; // Define a dummy constructor function.
f.prototype = p; // Set its prototype property to p.
return new f(); // Use f() to create an "heir" of p.
}
注意 __proto__
不是一个标准化属性,不应该在生产代码中使用,或者正如@alex在他的评论中指出的那样,它正在标准化的道路上。
注2:正如@thg435在他的评论中提到的,使用__proto__
属性的替代方法是使用ES6中标准化的Object.setPrototypeOf()
。
编辑以涵盖最后一个问题
sayweight和sayHello函数有什么区别?
不同之处在于,现在每个新的Person
实例(例如new Person()
(将具有不同的sayHello()
函数,但具有共享的sayWeight()
函数。
var friend = new Person();
var anotherFriend = new Person();
console.log(friend.sayHello === anotherFriend.sayHello); // OUTPUTS FALSE
console.log(friend.sayWeight === anotherFriend.sayWeight); // OUTPUTS TRUE
在这种情况下,原型有什么优势?
更少的内存,代码在所有 person 实例中重用,如果您已经有一个或多个 person 对象,并且想要向所有这些对象添加一个新方法而不依次修改每个对象,那么您可以将该方法添加到原型中,它们都将从中继承。
Person
不继承Person.prototype
,只有Person
的实例继承。此外,对于一个普通的对象,比如foo = {}
,foo.prototype
只是一个普通的属性。您要么需要一个构造函数,要么创建将其定义为具有特定原型的初始对象。
你真正想要的是
friend = Object.create(Person.prototype);
// or, for older browsers
friend = new Person();
// or some Object.create shim
/* which gives you
friend inherits Person.prototype
inherits Object.prototype */
这将设置原型链。如果你想结交很多朋友,最好设置一个新的构造函数Friend
,它有Friend.prototype = Object.create(Person.prototype);
。这还可以保护Person.prototype
,以防您要向Friend.prototype
添加属性。那么你会有
(instanceof) Friend inherits Friend.prototype
inherits Person.prototype
inherits Object.prototype
- JavaScript:访问继承子模块中的“封闭”变量
- 访问父“;这个“;变量,来自继承类
- 多重继承或访问对象外部的属性和方法
- AngularJS自定义指令在继承父作用域时访问模板中的属性
- 为什么允许通过原型继承访问另一个闭包范围内的私有变量
- 为什么并非所有属性都从内置对象(Javascript)继承/访问
- JavaScript 原型对象 - 如何访问继承
- Javascript 从父级中定义的继承类方法访问类变量
- Javascript继承,可以访问“超类”中的*所有*方法
- 母版页中包含的jQuery文件对于继承同一母版页的.aspx页不可访问
- 来自JavaScript继承方法的变量访问
- 如何在JavaScript中访问继承方法内部的私有属性
- 原型继承 - 访问原型属性中的道具
- 为什么继承的对象成员可以通过键访问,但是隐藏了'
- 如何在原型继承模式中访问方法
- TypeScript类可以移除对继承方法的访问吗?
- 是否有一种方法可以访问从基本模块继承的dojo功能
- 访问继承的修改对象的原始属性
- Javascript继承:子类型原型不能访问超类型的属性/函数
- 从基本提供程序继承时如何防止直接访问属性