• String调用Array相关方法——有点古怪 Benjamin


    这个系列的前面几篇文章中有谈到在一个Object上使用apply、call等方法操作另一个Object的方法,今天我们来学习怎么样在String上调用Array相关方法。 在许多方面,字符串表现的好像字符数组,许多Javascript array相关方法也可以使用在String类型上,但是并不是所有的方法都可以。看下面示例:

    var name = "Benjamin";
    
    //Outputs: TypeError: [].push.call(...) is read-only
    [].push.call(name, "is my name");

    报错:提示Javascript中字符串是只读的,因此任何方法想改变字符串都将失败,因此可以排除掉数组的push、pop、shift、unshift、splice方法。 但是仍有一些数组的方法是可以使用在字符串上的,看下例:

    var name = "Benjamin";
    
    var res01 = [].some.call(name, function(val, index, arr) {
    	//Outputs:String {0: "B", 1: "e", 2: "n", 3: "j", 4: "a", 5: "m", 6: "i", 7: "n", length: 8} 
    	console.log(arr);
    	return val === "B";
    });
    
    var res02 = [].every.call(name, function(val, index, arr) {
    	return val === "B";
    });
    
    var res03 = [].filter.call(name, function(val, index, arr) {
    	return val < "e";
    });
    
    //Outputs: true
    console.log(res01);
    
    //Outputs: false
    console.log(res02);
    
    //Outputs: ["B", "a"] 
    console.log(res03);

    详细了解some,every,filter方法的使用,请戳:Javascript Array.prototype.some()Javascript Array.prototype.every()Javascript Array.prototype.filter(),在字符串上操作数组方法是不是感觉挺棒的,但是大家要注意到filter方法返回的是一个数组,而不是一个字符串,而arr的输出值为一个json对象。但是细细想想,这也是有道理的,call和apply方法不会改变函数的逻辑,只改变它操作的值。 但是如果上例的filter方法需要我们返回字符串,我们可以使用链式操作:

    var name = "Benjamin";
    
    var res03 = [].filter.call(name, function(val, index, arr) {
    	return val < "e";
    }).join("");
    
    //Outputs: ["B", "a"] 
    console.log(res03);

    从上面来看,String是不能操作Array上的某些方法,但是我们该如何解决呢?解决此问题有一个相当简单的方式:我们可以先把字符串转换为字符数组,然后再转换为字符串。

    var name  = "Benjamin",
    	//TypeError: [].reverse.call(...) is read-only
    	//res01 = [].reverse.call(name),
    	res02 = [].slice.call(name).reverse().join("");
    
    //Outputs: ["B", "e", "n", "j", "a", "m", "i", "n"] 
    console.log([].slice.call(name));
    
    //Outputs: ["n", "i", "m", "a", "j", "n", "e", "B"] 
    console.log([].slice.call(name).reverse());
    
    //console.log(res01);
    
    // Outputs: nimajneB 
    console.log(res02);

    res01处如果放开也会报read-only错误,关于slice方法的使用看看MDN的描述:

    slice 不修改原数组,只会返回一个包含了原数组中提取的部分元素的一个新数组。原数组的元素会按照下述规则被拷贝("一级深拷贝"[one level deep]规则):

    如果该元素是个对象引用 (不是实际的对象),slice 会拷贝这个对象引用到新的数组里。两个对象引用都引用了同一个对象。

    如果被引用的对象发生改变,则改变将反应到新的和原来的数组中。 对于字符串和数字来说(不是 String 和 Number 对象),slice 会拷贝字符串和数字到新的数组里。在一个数组里修改这些字符串或数字,不会影响另一个数组。

    如果向两个数组任一中添加了新元素,则另一个不会受到影响。

    我们直接使用[].reverse.call转换没有成功,而借助slice方法来转换成字符串数组,并对其使用revserse方法,然后使用join方法再转换为字符串。 从上面的描述,有么有感觉到在String上使用Array的相关方法有点古怪,小陌生,但同时也可以很强大。希望本文简短的介绍对你在日常开发中有所帮助。 感谢您的阅读,文中不妥之处还望批评指正。如果你感觉本文对你有所帮助,请点赞!

  • 相关阅读:
    题解——草莓(树上切割)
    题解——碰杯
    SCOI2019凉凉记
    题解rotinv
    矩阵快速幂
    质数及线性筛
    题解[ZJOI2007]矩阵游戏
    【实验舱国庆营模拟】Day3 A.code
    【实验舱国庆营模拟】Day2 A.divide
    【纪中集训2019.08.25】【JZOJ6371】树
  • 原文地址:https://www.cnblogs.com/cuew1987/p/4063766.html
Copyright © 2020-2023  润新知