From 024c9d70ec9a9943f866731938df576b8e52b64b Mon Sep 17 00:00:00 2001 From: RainSun Date: Thu, 16 Jan 2020 19:53:49 +0800 Subject: [PATCH] finish book1 --- .../{javascript.md => javascript1.md} | 118 +++++++++++++++++- Miscellaneous/test.js | 68 ++++++---- 2 files changed, 160 insertions(+), 26 deletions(-) rename Miscellaneous/{javascript.md => javascript1.md} (67%) diff --git a/Miscellaneous/javascript.md b/Miscellaneous/javascript1.md similarity index 67% rename from Miscellaneous/javascript.md rename to Miscellaneous/javascript1.md index 541c2b8..248feb5 100644 --- a/Miscellaneous/javascript.md +++ b/Miscellaneous/javascript1.md @@ -209,4 +209,120 @@ // 3 ``` * 混合对象“类” - * \ No newline at end of file + * 设计模式:实例化,继承,(相对)多态 + * 多态并不能表示子类和父类有关联,子类得到的只是父类的一个副本,类的继承实际上就是复制 + * 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,就会调用这个setter,foo不会重新定义也不会直接添加到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` \ No newline at end of file diff --git a/Miscellaneous/test.js b/Miscellaneous/test.js index f2882fd..5b9950b 100644 --- a/Miscellaneous/test.js +++ b/Miscellaneous/test.js @@ -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) \ No newline at end of file +// 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() \ No newline at end of file