# 前言
参考: https://developer.mozilla.org/zh-CN/docs/Learn/JavaScript/Objects/Object_prototypes
# 摘要
JavaScript 常被描述为一种基于原型的语言 (prototype-based language)——每个对象拥有一个原型对象,对象以其原型为模板、从原型继承方法和属性。原型对象也可能拥有原型,并从中继承方法和属性,一层一层、以此类推。这种关系常被称为原型链 (prototype chain),它解释了为何一个对象会拥有定义在其他对象中的属性和方法。
准确地说,这些属性和方法定义在 Object 的构造器函数(constructor functions)之上的 prototype 属性上,而非对象实例本身。
在传统的 OOP 中,首先定义“类”,此后创建对象实例时,类中定义的所有属性和方法都被复制到实例中。在 JavaScript 中并不如此复制——而是在对象实例和它的构造器之间建立一个链接(它是
__proto__
属性,是从构造函数的 prototype 属性派生的),之后通过上溯原型链,在构造器中找到这些属性和方法。
__proto__
属性:对象实例和它的构造器之间的链接。
prototype
属性: prototype
属性包含(指向)一个对象,你在这个对象中定义需要被继承的成员。
默认情况下, 所有函数的原型属性的 __proto__
就是 window.Object.prototype
# 示例
function Person(first, last, age, gender, interests) {}
var person1 = new Person("Bob", "Smith", 32, "male", ["music", "skiing"]);
typeof Object.prototype;
// output: 'object'
typeof Object;
// output: 'function'
Person.prototype;
// output: {constructor: ƒ}constructor: ƒ Person(first, last, age, gender, interests)[[Prototype]]: Object
Person.__proto__;
// output: ƒ () { [native code] }
Object.prototype;
// output: {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
person1.__proto__ === Person.prototype;
// output: true
Person.__proto__ === Object.prototype;
// output: false
Person.prototype.__proto__ === Object.prototype;
// output: true
Person.__proto__ === Function.prototype;
// output: true
Function.prototype.__proto__ === Object.prototype;
// output: true
Object.__proto__ === Function.prototype
// output: true
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
# 对象的继承
function Person(first, last, age, gender, interests) {
this.name = {
first,
last
};
this.age = age;
this.gender = gender;
this.interests = interests;
};
undefined
Person.prototype.greeting = function() {
alert('Hi! I\'m ' + this.name.first + '.');
};
ƒ () {
alert('Hi! I\'m ' + this.name.first + '.');
}
function Teacher(first, last, age, gender, interests, subject) {
Person.call(this, first, last, age, gender, interests);
this.subject = subject;
}
undefined
const t = new Teacher()
VM755:1 Uncaught SyntaxError: Identifier 't' has already been declared
at <anonymous>:1:1
(anonymous) @ VM755:1
const tt = new Teacher()
undefined
tt.greeting
undefined
Teacher.prototype = Object.create(Person.prototype);
Person {}
tt.greeting
undefined // 这个为什么是undefined
const tt2 = new Teacher()
undefined
tt2.greeting
ƒ () {
alert('Hi! I\'m ' + this.name.first + '.');
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
因为如下原因
tt.__proto__ === tt2.__proto__
false
tt.__proto__
{constructor: ƒ}constructor: ƒ Teacher(first, last, age, gender, interests, subject)__proto__: Object
tt2.__proto__
Person {}__proto__: Object
2
3
4
5
6
# 相关知识点
- 通过原型添加新属性时是否可以访问已有属性:方法可
function Test(a,b,c,d) { this._a = a; };
// 定义第一个方法
function Test(a,b,c,d) {
this._a = a;
};
Test.prototype.x = function () { return this._a * this._a }
const t = new Test(11)
t.x()
// output: 121
2
3
4
5
6
7
8
9
10
11
12
- this
- call用法 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/call
- bind方法 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/bind
- apply https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Function/apply
- 类型判断:typeof instanceof
- Function
- Object
- class