简体   繁体   English

JavaScript扩展数组无法正常工作,没有错误消息

[英]JavaScript Extended Array doesn't work as expected with no error message

Hello I am a currently learning JavaScript for my project. 您好,我正在为我的项目学习JavaScript。 I have a question about this short code. 我对此简短代码有疑问。

function randomArr(){};
randomArr.prototype = new Array(); 
randomArr.prototype.getRandomValue = function(){
    var index = Math.floor(this.length * Math.random()); // return 0~1  
    return this[index];
}

var arr = new randomArr('seoul', 'tokyo', 'beijing');
console.log(arr.getRandomValue());

When I ran this code in Web-Browser, the output is just undefined. 当我在Web浏览器中运行此代码时,输​​出只是未定义的。

For me, it's better adding that function to Array type: 对我来说,最好将该函数添加到Array类型中:

Array.prototype.getRandomValue = function(){
    var index = Math.floor(this.length * Math.random()); // return 0~1  
    return this[index];
}

Array arr = new Array('seoul', 'tokyo', 'beijing');
console.log(arr.getRandomValue());

Take a look at this interesting explanation: https://coderwall.com/p/h4xm0w/why-never-use-new-array-in-javascript 看看这个有趣的解释: https : //coderwall.com/p/h4xm0w/why-never-use-new-array-in-javascript

According to that link, you should use arrays as follow: 根据该链接,您应该使用数组,如下所示:

var arr = ['seoul', 'tokyo', 'beijing'];
console.log(arr.getRandomValue());

Hope this helps! 希望这可以帮助!

One of the big benefits of ES6 classes is that they can subclass "exotic" classes, such as arrays. ES6类的一大好处是它们可以对“异类”类进行子类化,例如数组。 It's possible to trick older versions of Javascript into subclassing arrays, but not worth the trouble of explaining here. 可以将旧版本的Javascript欺骗到子类化数组中,但是不值得在这里进行解释。

Another concern is that you're using an extremely poor pattern of subclassing for pre-ES6 Javascript, to instantiate the base class and adding an instance of the base class to your new class's prototype chain, rather than gluing them first. 另一个问题是,您使用的ES6之前版本Javascript的子类继承模式非常差,可以实例化基类并将基类的实例添加到新类的原型链中,而不是先将它们粘在一起。 This is what Typescript does under the hood, but it makes some awful assumptions. 这是Typescript在后台执行的操作,但是做出了一些可怕的假设。 In your case, the Array constructor was already invoked long before you provided your list of cities, and created an empty array, so this would have failed even if you could subclass arrays like this. 在您的情况下,在提供城市列表之前,Array构造函数已经被调用很长时间,并且创建了一个空数组,因此即使您可以对此类进行子类化,也会失败。

This code is the modern way to do this. 此代码是执行此操作的现代方法。 I took the extra step of addressing the concern raised in Eleazar's link by not directly passing the constructor's arguments down to the Array base constructor, but instead letting the base constructor create an empty array, then pushing the values into it. 我采取了额外的步骤来解决Eleazar链接中提出的问题,方法是不直接将构造函数的参数传递给Array基本构造函数,而是让基本构造函数创建一个空数组,然后将值推入其中。

class randomArr extends Array{
    constructor(..._items){
        super()
        _items.forEach(_=>this.push(_))
    }
    getRandomValue(){
        const index=Math.floor(this.length*Math.random())
        return this[index]
    }
}

let arr=new randomArr('seoul', 'tokyo', 'beijing')
console.log(arr.getRandomValue())

Despite Eleazer's advice, I would avoid adding to core prototypes with named properties. 尽管有Eleazer的建议,但我还是避免添加具有命名属性的核心原型。 I have found Symbol properties to be perfect for this purpose. 我发现Symbol属性非常适合此目的。 Here's what that would look like: 如下所示:

const getRandomValue=Symbol()
Reflect.defineProperty(
    Array.prototype,
    getRandomValue,
    {
        value(){
            const index=Math.floor(this.length*Math.random())
            return this[index]
        }
    }
)

let arr=['seoul', 'tokyo', 'beijing']
console.log(arr[getRandomValue]())

The advantage of the symbol route is that you are guaranteed to not have name clashes with another library also extending the Array prototype. 符号路由的优点是可以确保您不会与另一个扩展Array原型的库发生名称冲突。

Here is a method using prototype chain and avoiding adding method directly to Array.prototype . 这是使用原型链并避免将方法直接添加到Array.prototype的方法。

function randomArr() {                                             
Array.call(this);                                                      
  for (x in arguments) {                                 
  this.push(arguments[x]);                                           
  }                                                                         
}                                                         

randomArr.prototype = Object.create(Array.prototype); 
randomArr.prototype.constructor = randomArr; 

randomArr.prototype.getRandomValue = function(){                          
var index = Math.floor(this.length * Math.random()); // return 0~1     
return this[index];                                         
}                                                                         

var arr = new randomArr('seoul', 'tokyo', 'beijing');      
alert(arr.splice(1,1));  // works as desired     
alert(arr.getRandomValue()); // works fine

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM