You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
functionFoo(who){this.me=who;}Foo.prototype.identify=function(){return`i am ${this.me}`;}functionBar(who){Foo.call(this,who);}Bar.prototype=Object.create(Foo.prototype);Bar.prototype.speak=function(){alert(`hello, ${this.identify()}`);}varb1=newBar('b1');varb2=newBar('b2');b1.speak();// hello, i am b1b2.speak();// hello, i am b2
对象关联风格
constFoo={init: function(who){this.me=who;},identify: function(){return`i am ${this.me}`}};constBar=Object.create(Foo);Bar.speak=function(){alert(`hello, ${this.identify()}`);}varb1=Object.create(Bar);b1.init('b1');varb2=Object.create(Bar);b2.init('b2');b1.speak();// hello, i am b1b2.speak();// hello, i am b2
关于this
定义
this 实际上是在函数被调用时动态发生的绑定,它指向什么完全取决于函数在哪里被调用
this指向优先级
柯里化的问题
当显式绑定传入第一个参数为null或者undefined的时候,this会被绑定至全局
当使用硬绑定来实现柯里化的时候,被绑定函数内部如果使用this,会导致操作全局对象
一个好的处理方式是:需要在显式绑定忽略this时,传入
DMZ
软绑定
箭头函数
根据当前的词法作用域来决定this,继承外层函数调用的this指向
优先级高于new
对象
万物皆对象的说法是错误的
基本类型和对象子类型(或称内置对象,比如String)是不等同的,javascript会在操作基本类型的时候自动将之转化为内置对象
基本类型中:boolean、string、number字面量与对应的内置对象不等同,null和undefined没有构造形式,而Object、Array、Function和RegExp无论使用字面量还是构造形式来声明,他们都是对象。
对象内容的存储
对象内容并不是存储在对象内部,而是通过属性名(键)来指向内存某一位置的值
可计算属性名
最常用的场景是ES6的Symbol,因为Symbol不透明且无法预测
Object.assign
Object.assign内部就是使用=操作符来赋值,以此实现浅拷贝。因此原对象属性的一些特性(writable等)不会被复制到目标对象
Object.defineProperty
如果目标对象引用了其他对象,这些属性特性的声明不会对子对象的内容产生作用
Object.preventExtensions()
Object.seal()
等于对现有对象调用Object.preventExtensions(),同时把所有现有属性设置为 configurable: false,即只能修改已有属性的值
Object.freeze()
等于对现有对象调用Object.seal(),同时把所有现有属性设置为 writable: false
getter 和 setter
当给一个属性定义getter,或setter或两者都有时,这个属性会被定义为”访问描述符“(区别于”数据描述符“),javascript会忽略它的value和writable特性,只关心set、get、configurable和enumerable(?实测会报错,不能同时设置get和value、writable)
in 和 Object.hasOwnProperty
in 操作符会检查属性名是否存在于对象或原型链中,而 Object.hasOwnProperty 只会检查属性是否存在对象中
propertyIsEnumerable
会检查属性名是否直接存在于对象上且可枚举
Object.keys
返回所有可枚举属性名的数组
Object.getOwnPropertyNames
返回一个数组,包含所有在对象上的属性,无论是否可枚举
iterator
Symbol.iterator 会指向一个'返回迭代器对象'的函数
for...of
for...of 会找到对象的
iterator
来处理遍历(每次调用next方法)数组天生自带
iterator
,所以可以被for...of遍历,但是普通对象不行,可以手动给想遍历的对象定义iterator
类和原型
类是一种设计模式
javascript的机制其实和类完全不同,虽然可以用一般意义上的类来理解(比如实例化,继承等),但是javascript所做的一切本质上只是在操作对象
属性设置和屏蔽
如果希望在3、4也屏蔽上层foo,就不能使用=操作符来赋值,可以通过Object.defineProperty()来添加 foo 属性
javascript”实例化“本质
在面向类的语言中,类可以被复制多次(类似用模具做东西)。但是在javascript中,并没有类似的复制方式,不能创建一个类的多个实例,只是创建了多个对象。它们的 prototype 关联的是同一个对象(引用),在默认情况下并不会复制。因此,在javascript中,”实例化的本质“是 —— 让两个对象相关联
new 操作符实际上并没有直接创建关联,这个关联只是个副作用(?!)
prototype.constructor
鉴于上述javascript实例化的本质,因此不能信任这条属性,不应该把它理解为”由...构造“。
寻找路径:
obj不存在
constructor
-> Foo.prototype不存在constructor
-> Object.prototype的constructor
指向 Object修正这种行为,必须显式的定义Foo.prototype.constructor
关于继承
重新指定 prototype.constructor 时
内省
__proto__实际上更像一个getter/setter,并不存在当前对象中,而是存在 Object.prototype 中。
委托
面向委托的设计模式
在javascript中,用委托代替继承来解释原型链更为恰当,因为本质上prototype的机制就是对象之间的关联关系
委托理论
Object.create 会创建一个新对象,并把它的__proto__委托到我们指定的对象
原型风格和对象关联风格
原型风格
对象关联风格
关于对象关联风格的思考:乍一看 b1 的初始化变为了两个步骤,需要更多代码。但其实这也是一个优点,把构造和初始化分离,在某些情况下更灵活
The text was updated successfully, but these errors were encountered: