Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/388.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
JavaScript对象继承(按对象)。从基元值创建_Javascript_Object_Inheritance_Prototypal Inheritance_Prototype Chain - Fatal编程技术网

JavaScript对象继承(按对象)。从基元值创建

JavaScript对象继承(按对象)。从基元值创建,javascript,object,inheritance,prototypal-inheritance,prototype-chain,Javascript,Object,Inheritance,Prototypal Inheritance,Prototype Chain,或 建议对象。create()在ES5中设计用于提供一种简单的方式来继承JavaScript对象 其工作原理如下所示: const A=function(){}; A.原型x=10; A.prototype.say=函数(){ console.log(this.x); }; 常数a=新的a(); a、 say()//10 常量b=对象。创建(a); b、 say()//10那些在JavaScript中被称为“装箱原语”的对象显然看起来很奇怪。让我们看看您发现了什么,以及如何通过原型使用派生来

建议对象。create()在ES5中设计用于提供一种简单的方式来继承JavaScript对象

其工作原理如下所示:

const A=function(){};
A.原型x=10;
A.prototype.say=函数(){
console.log(this.x);
};
常数a=新的a();
a、 say()//10
常量b=对象。创建(a);
b、 say()//10
那些在JavaScript中被称为“装箱原语”的对象显然看起来很奇怪。让我们看看您发现了什么,以及如何通过原型使用派生来做您想做的事情

首先,记住y=Object.create(x)的作用:它生成一个原型为x的新对象y

尼斯:
x
指的是一个对象,
y
是一个新对象,其原型是
x
。x引用的对象有一个可枚举、可配置、可写的值属性,名为
name
,由y继承。在x中,
name
是自己的属性;在
y
中,它是继承的属性。但在这两种情况下,房产都相当“正常”

现在让我们使用一个
Number
对象:

x = Object(3);                     // [Number: 3]
x.constructor;                     // [Function: Number]
typeof x;                          // "object"
x.valueOf();                       // 3
x + 0                              // 3
y = Object.create(x);
Object.getPrototypeOf(y) === x;    // true
x.isPrototypeOf(y);                // true

// So far so good, but now

y.valueOf()
    // TypeError: Number.prototype.valueOf requires that 
    // 'this' be a Number
y + 0
    // TypeError: Number.prototype.valueOf requires that 
    // 'this' be a Number
哇,刚才发生了什么事?这是不是说
y
不是一个数字?让我们检查一下:

y.constructor                      // [Function: Number]
嗯,它看起来确实像一个数字。由于
y
的原型是
x
,而
y
的原型是
Number.prototype
y
当然可以访问
Number.prototype
中的所有功能。但似乎无论我们称之为哪一种,例如:

y.toFixed(2)
y.toLocaleString()
等等,我们得到了那个错误!这里发生的事情是,
Number.prototype
中的所有这些函数都在检查对象的内部属性,它们希望看到一个原语。数字对象的此内部插槽未被继承,因此当您执行
y=object时。创建(x)
包含3的x插槽未被继承,因此在
y
中,该插槽不包含原始数字!
Number.prototype
中的所有方法都需要内部插槽(称为
[[NumberData]]]
…请官方使用原语值

现在向下滚动一点到第20.1.3节,您可以看到所有数字操作都试图通过抽象操作
thisNumberValue
提取
[[NumberData]]
插槽中的值,如果它没有签出,将抛出
TypeError
。这就是您看到的

这对你来说意味着什么

如果您想使用原型继承来创建一个新的数字对象,其原型是一个现有的数字对象,并以新对象的数值与原始对象相同的方式来创建,那么您不能直接在JavaScript中这样做。这不是
Number
对象的工作方式!但是,您可以创建自己的number类型,其中原语值存储在可继承属性中

您可以尝试的另一件事是:为每个原语创建自己的函数。例如:

function createNewNumber(original) {
    // n is expected to be a Number object
    const derived = new Number(original.valueOf());
    Object.setPrototypeOf(derived, original);
    return derived;
}
现在

这可能是您想要的,但请记住,您不能直接使用
对象。创建
!使用对象。在数字上创建不会继承
[[NumberData]]
属性,正如我们亲眼所见。您需要实现自己的派生函数并自行设置原型。这是一个黑客攻击,但我希望它能有所帮助

附录

至于为什么
[[NumberData]]
插槽没有被继承,这里引用了ES9规范:

内部插槽对应于与对象关联并由各种ECMAScript规范算法使用的内部状态。内部插槽不是对象属性,也不是继承的。根据特定的内部插槽规范,此类状态可能由任何ECMAScript语言类型或特定ECMAScr的值组成ipt规范类型值。除非另有明确规定,否则内部插槽是作为创建对象过程的一部分分配的,不能动态添加到对象中。除非另有规定,否则内部插槽的初始值是未定义的值。本规范中的各种算法创建的对象但是,ECMAScript语言没有提供将内部插槽与对象关联的直接方法

虽然这种语言清楚地表明无法在对象上创建或设置插槽,但似乎我们甚至无法检查插槽。因此,从对象中获取数值需要使用
object.prototype
中的程序员可访问的
valueOf
属性。除非执行一些疯狂的操作,如
object.create(null)
:)

那些在JavaScript中被称为“盒装原语”的对象显然看起来很奇怪。让我们看看您发现了什么,以及如何通过原型使用派生来做您想做的事情

首先,记住y=Object.create(x)
的作用:它生成一个原型为x的新对象y

尼斯:
x
指的是一个对象,
y
是一个新对象,其原型是
x
。x引用的对象有一个可枚举、可配置、可写的值属性,名为
name
,由y继承。在x中,
name
是自己的属性;在
y
中,它是继承的属性。但在这两种情况下,房产都相当“正常”

现在让我们使用一个
Number
对象:

x = Object(3);                     // [Number: 3]
x.constructor;                     // [Function: Number]
typeof x;                          // "object"
x.valueOf();                       // 3
x + 0                              // 3
y = Object.create(x);
Object.getPrototypeOf(y) === x;    // true
x.isPrototypeOf(y);                // true

// So far so good, but now

y.valueOf()
    // TypeError: Number.prototype.valueOf requires that 
    // 'this' be a Number
y + 0
    // TypeError: Number.prototype.valueOf requires that 
    // 'this' be a Number
哇,刚才发生了什么事?这是不是说
y
不是一个数字?让我们检查一下:

y.constructor                      // [Function: Number]
嗯,它看起来确实像一个数字。由于
y
的原型是
x
,而
y
的原型是
Number.prototype
y
当然可以访问
Number.prototype
中的所有功能。但似乎无论我们称之为哪一个,例如: