我知道这会起作用:
function Foo() {}; Foo.prototype.talk = function () { alert('hello~\n'); }; var a = new Foo; a.talk(); // 'hello~\n'
但是如果我想打电话
Foo.talk() // this will not work Foo.prototype.talk() // this works correctly
我找到一些Foo.talk工作方法,
Foo.talk
Foo.__proto__ = Foo.prototype
Foo.talk = Foo.prototype.talk
还有其他方法吗?我不知道这样做是否正确。您在JavaScript代码中使用类方法还是静态方法?
首先,请记住JavaScript主要是一种原型语言,而不是基于类的语言1。Foo不是一个类,而是一个函数,这是一个对象。您可以使用关键字从该函数实例化一个对象,该new关键字将允许您使用标准OOP语言创建类似于类的内容。
Foo
new
我建议__proto__大部分时间都忽略它,因为它对跨浏览器的支持很差,而应该专注于了解其prototype工作原理。
__proto__
prototype
如果您有一个从函数2创建的对象的实例,并且以任何方式访问其成员之一(方法,属性,属性,常量等),则访问将沿原型层次结构进行,直到(a)找到成员,或(b)找不到其他原型。
层次结构从被调用的对象开始,然后搜索其原型对象。如果原型对象具有原型,则重复该操作(如果不存在原型),undefined则返回该对象。
undefined
例如:
foo = {bar: 'baz'}; console.log(foo.bar); // logs "baz" foo = {}; console.log(foo.bar); // logs undefined function Foo(){} Foo.prototype = {bar: 'baz'}; f = new Foo(); console.log(f.bar); // logs "baz" because the object f doesn't have an attribute "bar" // so it checks the prototype f.bar = 'buzz'; console.log( f.bar ); // logs "buzz" because f has an attribute "bar" set
在我看来,您已经至少已经对这些“基本”部分有所了解,但是为了确保它们,我需要使它们明确。
在JavaScript中,一切都是对象3。
一切 都是对象。
function Foo(){}不仅定义了一个新函数,还定义了一个可以使用访问的新函数对象Foo。
function Foo(){}
这就是为什么您可以使用来访问Foo的原型的原因Foo.prototype。
Foo.prototype
你也可以做的是设置 更多的功能 上Foo:
Foo.talk = function () { alert('hello world!'); };
可以使用以下方式访问此新功能:
Foo.talk();
我希望到目前为止,您已经注意到函数对象上的函数与静态方法之间的相似性。
可以将其f = new Foo();视为创建类实例,Foo.prototype.bar = function(){...}为该类定义共享方法以及为该类Foo.baz = function(){...}定义公共静态方法。
f = new Foo();
Foo.prototype.bar = function(){...}
Foo.baz = function(){...}
ECMAScript 2015为此类声明引入了多种语法糖,以使其更易于实现,同时也更易于阅读。因此,前面的示例可以写成:
class Foo { bar() {...} static baz() {...} }
它可以bar被称为:
bar
const f = new Foo() f.bar()
并被baz称为:
baz
Foo.baz()
1:class是ECMAScript5规范中的“未来保留字”,但是ES6引入了使用class关键字定义类的功能。
class
2:本质上是由构造函数创建的类实例,但是有很多细微的差别我不想误导你
3:基本值(包括undefined,,null布尔值,数字和字符串)在技术上不是对象,因为它们是低级语言实现。布尔值,数字和字符串仍然像它们是对象一样与原型链交互,因此,出于此答案的目的,即使它们不是完全一样,也更容易将它们视为“对象”。
null