finish book1

This commit is contained in:
RainSun 2020-01-16 19:53:49 +08:00
parent 446366a32f
commit 024c9d70ec
2 changed files with 160 additions and 26 deletions

View File

@ -209,4 +209,120 @@
// 3
```
* 混合对象“类”
*
* 设计模式:实例化,继承,(相对)多态
* 多态并不能表示子类和父类有关联,子类得到的只是父类的一个副本,类的继承实际上就是复制
* super关键字用于访问和调用一个对象的父对象上的函数。`super.prop``super[expr]`表达式在类和对象字面量任何方法定义中都是有效的。
* js本身并不支持多重继承
* 类意味着复制js并不会自动创建对象的副本
* 混入模式可以模拟类的复制行为,但是会产生丑陋并且脆弱的语法。
* 而且对象函数只能复制引用无法复制被引用的对象或者函数本身所以在js中模拟类是得不偿失的虽然可以解决当前的问题但是可能会留下更多的隐患
* 原型
* `Object.create(...)`创建一个对象并将其`prototype`关联到指定对象
* 所有对象的`prototype`最终都指向了内置的`Object.prototype`其中包含类如`.toString();.valueOf()`之类的方法
* 分析如果foo不直接存在于obj上而是存在于原型链上层时会出现的三种情况
* 如果上层的foo是普通的数据访问属性并且没有被标记为只读那就会在对象上直接创建foo属性它是遮蔽属性
* 如果上层的foo是只读属性的话严格模式下会抛出一个错误正常模式下静默失败可以理解为obj继承了foo但是foo是只读属性所以不可更改实际上js并没有继承这一概念只是为了理解、
* 而且仅限于 = 赋值中,使用`Object.defineProperty()`并不会受到任何影响
* 如果上层的foo存在且是一个setter就会调用这个setterfoo不会重新定义也不会直接添加到obj中
* 模仿类:
* 利用所有函数都会拥有一个名为`prototype`的共有且不可枚举的属性,并且会指向另一个对象
* 通过`new foo()`最后我们得到了两个对象并且他们互相关联实际上new并没有直接创建关联这个关联只是一个意外的副作用
* new 会劫持所有的函数并用构造对象的形式来调用它而且无论如何都会构造一个对象换句话说在js中对于“构造函数”最准确的解释是所有带new的函数调用
* 函数被创建的时候会默认在其`prototype`中声明一个不可枚举的`construct`属性,指向它自己,使用`new`创建一个对象的时候由于其`prototype`会链接到函数的`prototype`上,所以`obj.construct`会委托到`prototype`上也就是指向了函数,但是如果那个函数重定义了整个`prototype`,再去查找`obj.construct`就会一层一层委托到`Object``construct`上,也就是指向`Object`总结一下就是说construct并不能表示由“某函数”创建尽量不要使用它以减少麻烦
* 实现类的继承,实际上是委托
* 方法一`Bar.prototype = Object.create(Foo.prototype)`
* 方法二`Object.setPrototypeOf(Bar.prototype, Foo.prototype)` ES6语法
* `__proto__`存在于`Object.prototype`看起来像一个属性但是更像是getter/setter
* 创建关联最好的方式不是创建一个类,而是使用`Object.create()`
* 所有包含"继承"之类的词语都不适合形容js的操作更应该使用"委托",因为“继承”是复制操作(由上至下的),"委托"是链接操作(由下至上的)
* 行为委托
* js中`[[prototype]]`这个机制的本质就是**对象之间的关联关系**
* 在正常的模仿类的设计中,上代码!
```js
function Foo(who) {
this.me = who
}
Foo.prototype.indetify = function() {
return "I am" + this.me
}
function Bar(who) {
Foo.call(this, who)
}
Bar.prototype = Object.create(Foo.prototype)
Bar.prototype.speak = function() {
alert('Hello,'+ this.indetify() + '.')
}
var b1 = new Bar('b1')
var b2 = new Bar('b2')
b1.speak()
b2.speak()
```
* 在es6的语法糖中上代码
```js
class Foo {
constructor(who) {
this.me = who
}
indetify(){
return "I am" + this.me
}
}
class Bar extends Foo {
constructor(who) {
super(who)
}
speak(){
alert('Hello,'+ super.indetify() + '.')
}
}
var b1 = new Bar('b1')
var b2 = new Bar('b2')
b1.speak()
b2.speak()
```
* 在关联风格代码中的实现,上代码!
```js
var Foo = {
init: function(who) {
this.me = who
},
indetify: function() {
return "I am" + this.me
}
}
var Bar = Object.create(Foo)
Bar.speak = function() {
alert('Hello,'+ this.indetify() + '.')
}
var b1 = Object.create(Bar)
b1.init('b1')
var b2 = Object.create(Bar)
b2.init('b2')
b1.speak()
b2.speak()
```
* 同为关联风格代码但是进行了语法上的优化es6中的简洁方法声明Object.setPrototypeOf后置关联这样看起来舒服不少
```js
var Foo = {
init(who) {
this.me = who
},
indetify() {
return "I am" + this.me
}
}
var Bar = {
speak() {
alert('Hello,'+ this.indetify() + '.')
}
}
Object.setPrototypeOf(Bar, Foo)
var b1 = Object.create(Bar)
b1.init('b1')
var b2 = Object.create(Bar)
b2.init('b2')
b1.speak()
b2.speak()
```
* instanceof 如果 Bar”继承了“Foo 那么就是 `Bar.prototype instanceof Foo => true`
* 如果`Bar = Object.create(Foo)``Foo.isPrototypeOf(Bar) => true`,`Object.getPrototypeOf(Bar) === Foo => ture`

View File

@ -54,30 +54,48 @@
// console.log(test)
// console.log(test1)
var obj = {
// set a(val) {
// this._a_ = val * 2
// },
// get a() {
// return this._a_
// },
// var obj = {
// // set a(val) {
// // this._a_ = val * 2
// // },
// // get a() {
// // return this._a_
// // },
}
Object.defineProperty(
obj,
'a',
{
set: function(val) {
this._a_ = val * 2
},
get: function() {
return this._a_
},
// }
// Object.defineProperty(
// obj,
// 'a',
// {
// set: function(val) {
// this._a_ = val * 2
// },
// get: function() {
// return this._a_
// },
writable: false,
enumerable: true
}
)
obj.a = 2
console.log(obj)
console.log(obj.a)
// writable: false,
// enumerable: true
// }
// )
// obj.a = 2
// console.log(obj)
// console.log(obj.a)
function Foo(who) {
this.me = who
}
Foo.prototype.indetify = function() {
return "I am" + this.me
}
function Bar(who) {
Foo.call(this, who)
}
Bar.prototype = Object.create(Foo.prototype)
Bar.prototype.speak = function() {
alert('Hello,'+ this.indetify() + '.')
}
var b1 = new Bar('b1')
var b2 = new Bar('b2')
b1.speak()
b2.speak()