1 前言
javascript 是具有基于原型链
的面向对象编程语言
oop
!= class
oop
也不需要基于class
2 在javascript中,对象来自于对象Object comes from Object
。你可以使用对象来直接构造一个对象
example #1
1
2
3
4
5
6var food = {
eat:"i eat !"
}
var meal = Object.create(food)
console.log(meal.eat) // "i eat"
现在我来解释下这里发生了什么,首先Object.create(source)方法创建了一个新的空对象,然后将新对象的原型设置为source即你传入对象。
2.1 首先来验证下meal确实是空对象
console.log(meal) // {}
2.2 然后我们来验证meal的原型确实是food
meal.__proto__ === food //true
2.3 你可能会问:等等!__proto__
是什么??? 为什么meal.eat 输出了内容
???
2.3.1 先回答第一个问题:__proto__
是什么?
在javascript中所有的对象中都有一个内置属性__proto__
,指向它的原型对象。
在这个例子中meal
的原型对象就是food
所有对象的原型指向形成了链式结构,这就是原型链,而原型链的顶端就是Object.prototype
meal.__proto ->food food.__proto->Object.prototype
Object.prototype
的原型是null
Object.prototype.__proto__ -> null
知道这个原理之后我们就可以来模拟一下Object.create()
example#2
1
2
3
4
5
6
7
8
9
10
11function ourNew(source){
var obj = {}
obj.__proto__ = source
return obj
}
var food = {
eat:"i eat"
}
var meal = ourNew(food)
console.log(meal.eat)//"i eat"
太棒了,我们模拟了一个对象的继承
2.3.2 再回答第二个问题:为什么meal.eat 输出了内容
?
js中对象属性的查找机制,是从对象本身开始查找,如果查找不到,则顺着原型链
继续向上查找,直到找到对应属性后返回,否则返回undefined
即meal.__proto__.__proto__...
当原型链中存在相同属性时候,最先找到的会被返回,而上层的同名属性会被屏蔽
example #3
1
2
3
4
5
6
7
8
9var food = {
eat:"i eat !"
}
var meal = Object.create(food)
console.log(meal.eat)//"i eat"
meal.eat = "i don't eat"
console.log(meal.eat)//"i don't eat"
console.log(meal.__proto__.eat)//"i eat" oops! food的eat属性被meal屏蔽了
3 构造函数 new 关键词
在js中我们还可以通过一类特殊的对象 — 函数 来构建对象,也就是我们经常说的构造函数。
任何函数只要前面加上关键词new
就会被当作是构造函数
example #4
1
2
3
4
5
6
7function Point(x,y){
this.x = x
this.y = y
}
var point = new Point(1,2)
console.log(point)//{x:1,y:2}
这其中发生了什么呢?
1 首先一个对象被创建,对象的_proto_
是Point.prototype
即构造函数.prototype
2 将this绑定到这个对象,用参数构造这个对象,即 新创建对象的x
变为传入参数 x
,新创建对象的y
变为传入参数的 y
3 如果构造函数没有显式返回一个对象,则返回新创建的对象
example #5
1
2
3
4
5
6
7
8function Point(x,y){
this.x = x
this.y = y
return {x:100,y:100}//显式返回对象 覆盖新建立的对象
}
var point = new Point(1,2)
console.log(point)//{x:100,y:100}
所以在js中对象直接来自对象,不管你是用object.create() 还是 new function()来创建