First off, remember that JavaScript is primarily a prototypal language , rather than a class-based language 1 .
(首先,请记住JavaScript主要是一种原型语言 ,而不是基于类的语言 1 。)
Foo
isn't a class, it's a function, which is an object.(Foo
不是类,而是函数,是对象。)
You can instantiate an object from that function using the new
keyword which will allow you to create something similar to a class in a standard OOP language.(您可以使用new
关键字从该函数实例化一个对象,该关键字将允许您使用标准OOP语言创建类似于类的内容。)
I'd suggest ignoring __proto__
most of the time because it has poor cross browser support, and instead focus on learning about how prototype
works.
(我建议大多数时候都忽略__proto__
,因为它对跨浏览器的支持不佳,而应该专注于学习prototype
工作方式。)
If you have an instance of an object created from a function 2 and you access one of its members (methods, attributes, properties, constants etc) in any way, the access will flow down the prototype hierarchy until it either (a) finds the member, or (b) doesn't find another prototype.
(如果您有一个从函数2创建的对象的实例,并且以任何方式访问其成员之一(方法,属性,属性,常量等),则访问将沿原型层次结构进行,直到(a)找到成员,或(b)找不到其他原型。)
The hierarchy starts on the object that was called, and then searches its prototype object.
(层次结构从被调用的对象开始,然后搜索其原型对象。)
If the prototype object has a prototype, it repeats, if no prototype exists, undefined
is returned.(如果原型对象具有原型,则重复该操作,如果不存在原型,则返回undefined
。)
For example:
(例如:)
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
It looks to me like you've at least somewhat understood these "basic" parts already, but I need to make them explicit just to be sure.
(在我看来,您已经至少已经对这些“基本”部分有所了解,但是为了确保它们,我需要使它们明确。)
In JavaScript, everything is an object 3 .
(在JavaScript中,一切都是对象3 。)
everything is an object.
(一切都是对象。)
function Foo(){}
doesn't just define a new function, it defines a new function object that can be accessed using Foo
.
(function Foo(){}
不仅定义了一个新函数,还定义了一个可以使用Foo
访问的新函数对象。)
This is why you can access Foo
's prototype with Foo.prototype
.
(这就是为什么您可以使用Foo.prototype
访问Foo
的原型的原因。)
What you can also do is set more functions on Foo
:
(您还可以在Foo
上设置更多功能 :)
Foo.talk = function () {
alert('hello world!');
};
This new function can be accessed using:
(可以使用以下方式访问此新功能:)
Foo.talk();
I hope by now you're noticing a similarity between functions on a function object and a static method.
(我希望到目前为止,您已经注意到函数对象上的函数与静态方法之间的相似性。)
Think of f = new Foo();
(想想f = new Foo();
)
as creating a class instance, Foo.prototype.bar = function(){...}
as defining a shared method for the class, and Foo.baz = function(){...}
as defining a public static method for the class.(创建类实例时, Foo.prototype.bar = function(){...}
为该类定义共享方法,而Foo.baz = function(){...}
为该类定义公共静态方法类。)
ECMAScript 2015 introduced a variety of syntactic sugar for these sorts of declarations to make them simpler to implement while also being easier to read.
(ECMAScript 2015为此类声明引入了多种语法糖,以使其更易于实现,同时也更易于阅读。)
The previous example can therefore be written as:(因此,前面的示例可以写成:)
class Foo {
bar() {...}
static baz() {...}
}
which allows bar
to be called as:
(允许将bar
称为:)
const f = new Foo()
f.bar()
and baz
to be called as:
(和baz
被称为:)
Foo.baz()
1: class
was a "Future Reserved Word" in the ECMAScript 5 specification , but ES6 introduces the ability to define classes using the class
keyword.
(1: 在ECMAScript 5规范中 , class
是“未来保留字” ,但是ES6引入了使用class
关键字定义类的功能。)
2: essentially a class instance created by a constructor, but there are many nuanced differences that I don't want to mislead you
(2:本质上是由构造函数创建的类实例,但是有很多细微的差别我不想误导你)
3: primitive values —which include undefined
, null
, booleans, numbers, and strings—aren't technically objects because they're low-level language implementations.
(3: 基本值(包括undefined
, null
,布尔值,数字和字符串)在技术上不是对象,因为它们是底层语言实现。)
Booleans, numbers, and strings still interact with the prototype chain as though they were objects, so for the purposes of this answer, it's easier to consider them "objects" even though they're not quite.(布尔值,数字和字符串仍然像它们是对象一样与原型链交互,因此,出于此答案的目的,即使它们并非完全相同,也更容易将它们视为“对象”。)