我发现我可以像这样扩展Object:
class MyObject extends Object {}
与此有什么不同而根本没有延伸,如下:
class MyObject {}
我问这个的原因是因为我有以下mixin:
const MapMixin = (Base = Object) => class extends Base {
static from(array) {
return new this(Object.assign(...array.map(([key, value]) => ({[key]: value}))));
}
map(...args) {
return this.constructor.from(this.entries().map(...args));
}
entries() {
return Object.entries(this);
}
};
这个mixin可以这样使用:
class MyObject extends MapMixin(MyBaseClass) {}
但是如果没有基类,我现在已经指定它然后默认扩展Object
:
class MyObject extends MapMixin() {}
所以我想知道,如果这实际上和没有任何扩展一样有效。
答案 0 :(得分:3)
我不知道这里的其他答案是否清楚,但区别在于静态继承。
在class
关键字之前,JavaScript中的继承一直非常关注实例继承。没有人(我已经看过)关心让一个类/构造函数从超类/构造函数继承静态成员。更不用说实现这一目标的唯一方法是通过非标准的__proto__
属性。
因此,当我们今天查看扩展另一个类的类时,我们会考虑继承如何在该类的实例之间起作用。例如,扩展Object
或根本不扩展是相同的,因为实例本身将继承Object
作为基础。
class A {}
class B extends Object {}
let a = new A()
let b = new B()
// a.__proto__.__proto__ === b.__proto__.__proto__ === Object.prototype
但可能并不清楚,或者很清楚extends
关键字不只是为实例设置继承。它还设置了类构造函数之间的继承。因此,对于上面的B
,使用extends
也意味着在后台为B调用Object.setPrototypeOf(B, Object)
。例如:
class A {} // A constructor inherits nothing (is a basic Function type)
class B extends Object {} // B inherits from Object
// A.setPrototypeOf === undefined
// B.setPrototypeOf === Object.setPrototypeOf
B
,延伸Object
,继承Object
的所有静态方法,而A
不延伸任何内容,不会。
区别在于B.prototype
(或B.prototype.__proto__
) - 继承自哪些实例,以及B.__proto__
- 类构造函数从哪个实例继承。是否Object
扩展不会影响prototype
或实例继承的内容,但会影响类__proto__
或静态继承。
答案 1 :(得分:2)
有一个微妙的区别。
如果您声明类A,B并创建如下的实例:
#data
df <- data.frame(City = c("NY", "AMS", "BER", "PAR", "NY", "AMS", "AMS", "PAE"),
Time_Diff = c(4, 2, 7, 9, 2, 1, 10, 9),
Outliers = c(0, 0, 0, 0, 0, 1, 1, 0))
#data summary
summary <- df %>%
group_by(City) %>%
summarise(Median = median(Time_Diff),
IQR = IQR(Time_Diff),
Outliers = sum(Outliers)) %>%
arrange(desc(Median), desc(IQR), desc(Outliers))
summary <- as.data.frame(summary)
# Preproces data for figure
order_city <- summary$City
# Create ggplot object
bp <-ggplot(data = df, aes(x = reorder(City, Time_Diff, FUN = median), y= Time_Diff)) # Creates boxplots
# Create boxplot figure
bp +
geom_boxplot(outlier.shape = NA) + #exclude outliers to increase visibility of graph
coord_flip(ylim = c(0, 25)) +
geom_hline(yintercept = 4) +
ggtitle("Time Difference") +
ylab("Time Difference") +
xlab("City") +
theme_light() +
theme(panel.grid.minor = element_blank(),
panel.border = element_blank(), #remove all border lines
axis.line.x = element_line(size = 0.5, linetype = "solid", colour = "black"), #add x-axis border line
axis.line.y = element_line(size = 0.5, linetype = "solid", colour = "black")) + #add y-axis
scale_x_discrete(limits = rev(order_city)) #this is the function to change the order of the axis
class A {}
class B extends Object {}
let a = new A()
let b = new B()
是基类,A
是派生类。
因此,B
直接从a
分配,但A
是从b
分配的。
所以你可以找到他们的原型:
Object
通过http://2ality.com/2015/02/es6-classes-final.html#the-extends-clause。
答案 2 :(得分:1)
正如Shu Ding所说,原型链不同
更明确:
const getNProtos = (n, { __proto__:p }={}, protos=[]) => n && p ? getNProtos(n-1, p, [ ...protos, p ]) : [ ...protos, p ]
[
class extends Object{},
class extends (class {}){},
class {}
].map(obj => getNProtos(3, obj)
.forEach(x => x.forEach(y => console.log(y)) || console.log('\n'))
)
ƒ Object() { [native code] }
ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null
class {}
ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null
ƒ () { [native code] }
{constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …}
null
原型链几乎相同,派生类在链上面只有一个额外的(对象构造函数)。使用Object扩展看起来类似于使用普通class {}
进行扩展,当然除了Object有自己的方法可用。