关于差异阅读的内容很多,提到数组是Javascript中的特殊对象类。例如此处:
https://www.codingame.com/playgrounds/6181/javascript-arrays---tips-tricks-and-examples
因此,由于object
是属性(或键)和值的集合,所以我在考虑是否有一种方法可以从一个对象开始并以一个数组结束(从某种意义上说,该方法Array.isArray()
对于模拟数组的对象返回true
。我已经开始查看数组属性:
let arr = [0, 1, 2, 3, 4, 5];
console.log(Object.getOwnPropertyNames(arr));
console.log(Array.isArray(arr));
所以我试图使用一个对象来模拟相同的东西:
let arrEmulation = {0:0, 1:1, 2:2, 3:3, 4:4, 5:5, "length":6};
console.log(Object.getOwnPropertyNames(arrEmulation));
console.log(Array.isArray(arrEmulation));
但是Array.isArray(arrEmulation)
仍返回false
。首先,如果这是一个愚蠢的问题,我想道歉,但是有什么方法可以手动将object
转换为array
并为其添加特殊属性(或键) ?
请注意,我不想知道如何将对象转换为数组,我只是想了解哪些特殊的东西可以解释像数组一样的对象。
>
答案 0 :(得分:6)
考虑到标准规范,从最严格的意义上讲,我认为这是不可能的。查找Array.isArray:
如果arg的[[Class]]内部属性的值为“ Array”,则返回true。
因此,为了使Array.isArray(arrEmulation)
返回true
,您必须以某种方式将对象的[[Class]]
修改为Array
,而不是Object
。但是,请查看ES5关于[[Class]]
的{{3}}:
注意:本规范未定义任何ECMAScript语言运算符或内置函数,这些运算符或内置函数不允许程序修改对象的[[Class]]或[[Prototype]]内部属性或将[[Extensible]]的值更改为从虚假到真实。修改[[Class]],[[Prototype]]或[[Extensible]]的特定于实现的扩展不得违反上一段中定义的不变式。
也:
请注意,除非通过
,否则本规范不提供任何程序访问该值的方法。Object.prototype.toString
因此,官方规范没有在ES5中提供执行此操作的方法-如果有 执行操作的方法,那么它将是非标准的且取决于实现。
也就是说,除非您绝对需要使用Array.isArray
或让Object.prototype.toString.call(arrEmulation)
返回[object Array]
,否则您仍然可以使用Object.setPrototypeOf
进行设置arrEmulation
到Array.prototype
的原型,允许您在对象上使用数组方法并使instanceof Array
返回true
:
const arrEmulation = {0:0, 1:1, 2:2, "length":6};
Object.setPrototypeOf(arrEmulation, Array.prototype);
console.log(arrEmulation instanceof Array);
arrEmulation.forEach((value) => {
console.log(value);
});
// Internal [[Class]] property is still `Object`, though:
console.log(Object.prototype.toString.call(arrEmulation));
// Unlike a true array:
console.log(Object.prototype.toString.call([]));
console.log('-----');
// although you can set the `toStringTag` to the string 'Array' in ES6+,
// it is cosmetic only and does not pass an `Array.isArray` test:
arrEmulation[Symbol.toStringTag] = 'Array';
console.log(Object.prototype.toString.call(arrEmulation));
console.log(Array.isArray(arrEmulation));
但是请注意,您应该8.6.2 Object Internal Properties and Methods在真实代码中使用Object.setPrototypeOf
:
警告:根据现代JavaScript引擎如何优化属性访问的性质,更改对象的
[[Prototype]]
在每个浏览器和JavaScript引擎中的操作都非常缓慢。对更改继承的性能的影响微妙而广泛,不仅限于在Object.setPrototypeOf(...)
语句中花费的时间,还可以扩展到任何可访问其[[Prototype]]
对象的代码已更改。如果您关心性能,则应避免设置对象的[[Prototype]]
。而是使用[[Prototype]]
使用所需的Object.create()
创建一个新对象。
(当然,Object.create
涉及创建一个 new 对象,该对象不同于您想要执行的操作,即更改现有的arrEmulation
对象)>
在ES6 +中也似乎没有一种方法可以实现-它的文本有点相似,但不完全相同。具体来说,为使Array.isArray
返回true
,有问题的对象avoid是“数组奇异对象”(或指向一个的Proxy
)-但是{{1} }仅设置原型,它或任何其他方法都不能使对象实际上成为 Array异类对象(看起来它必须由解释器本地构造,并且不能充分仿真)。
答案 1 :(得分:2)
Javascript全部涉及原型继承:
Prototype Inheritance 所有JavaScript对象都从 原型:
日期对象继承自Date.prototype数组对象继承自Date Array.prototype Person对象继承自Person.prototype Object.prototype位于原型继承链的顶部:
日期对象,数组对象和Person对象继承自 Object.prototype。
如此处所示,isArray是Array对象原型链中的一个函数。
如果MDN Array.isArray()中不存在isArray,则建议使用polyfill:
if (!Array.isArray) {
Array.isArray = function(arg) {
return Object.prototype.toString.call(arg) === '[object Array]';
};
}
所以类型是由原型链决定的,而不是它返回什么值。
类似地,根据Tio Zed的回答
const newArray = Array.from(arrEmulation) // [0, 1, 2, 3, 4, 5] Array.isArray(newArray)
它的真正作用是将原型从对象的原型更改为数组的原型。
isArray的更深入研究,感谢@Kaiido使我更深入。 数组是数组检查these there points
如果Type(arg)不是Object,则返回false。 如果arg的[[Class]]内部属性的值为“ Array”, 然后返回true。返回false。
Array实例从Array原型对象继承属性,并且 它们的[[Class]]内部属性值为“ Array”。阵列实例 也具有以下属性。
答案 2 :(得分:0)
您可以使用Array.from()转换与数组足够接近的任何内容。 在您的示例中,我们可以调用:
if(isset($_REQUEST["term"])){
// Prepare a select statement
$term = $_REQUEST['term'];
$sql = "SELECT * FROM fresh WHERE
description LIKE '%{$term}%' or
sku like '%{$term}%'
union
SELECT * FROM marine WHERE
description LIKE '%{$term}%' or
sku like '%{$term}%'";
if($stmt = mysqli_prepare($link, $sql)){
// Bind variables to the prepared statement as parameters
mysqli_stmt_bind_param($stmt, "s", $param_term);
// Set parameters
$param_term = $_REQUEST["term"] . '%';