JavaScript扩展数组无法按预期工作,没有错误消息

问题描述 投票:-1回答:3

您好我是我目前正在学习的项目JavaScript。我对这个简短的代码有疑问。

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());

当我在Web浏览器中运行此代码时,输​​出是未定义的。

javascript arrays
3个回答
2
投票

对我来说,最好将该函数添加到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());

看看这个有趣的解释:https://coderwall.com/p/h4xm0w/why-never-use-new-array-in-javascript

根据该链接,您应该使用如下数组:

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

希望这可以帮助!


1
投票

ES6类的一大好处是它们可以子类化“异类”类,例如数组。可以将旧版本的Javascript引入子类化数组,但不值得在此解释。

另一个问题是,您正在使用非常差的子类化模式来进行ES6之前的Javascript,实例化基类并将基类的实例添加到新类的原型链中,而不是先粘贴它们。这就是Typescript在幕后所做的事情,但它做了一些可怕的假设。在您的情况下,在您提供城市列表之前很久就调用了Array构造函数,并创建了一个空数组,因此即使您可以像这样子类化数组也会失败。

此代码是执行此操作的现代方法。我采取了额外的步骤来解决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())

尽管Eleazer的建议,我会避免添加具有命名属性的核心原型。我发现Symbol属性非常适合这个目的。这是什么样子:

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]())

符号路径的优点是保证不会与另一个库发生名称冲突,也会扩展Array原型。


0
投票

这是一个使用原型链并避免直接向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
© www.soinside.com 2019 - 2024. All rights reserved.