关于Array.prototype.slice.call的思考

var string1= 'helloword';
var a=Array.prototype.slice.call(string1);
console.log(a);

上面那个代码不用多说了吧 我一直认为可以通过这种方式用Array的方法直接通过call操作处理其他对象比如string;

今天我写的:
 var string1= 'helloword';
 var a=Array.prototype.reverse.call(string1);
 console.log(a);
 
 报这个错:
 

clipboard.png
有没有人能从原理解释一下这个是什么情况 谢谢了

阅读 3.2k
4 个回答

reverse是一个mutate的操作,也就是说改变传入的参数,比如说一个数组的reverse,在函数过程中会有类似的操作

//交换首尾的值
let len = a.length
let temp = a[0]

a[0] = a[len - 1]
a[len - 1] = temp

但是你能对一个字符串进行这样的操作吗?不行,字符串在javascript里是基本类型,是immutable的,是只读的

let a = 'abcdef'
a[0] // 'a'
a[0] = 'e' // a 并不会变,还是'abcedf'

那么很明显,我们不需要知道reverse的实现细节,我们只需要知道它是一个mutate的方法,就可以确定,它不能实现字符串的反转,如果你想知道为什么么会出现提示的错误,你可以去看看es标准或者v8源码的具体实现。

那么同理,slice是返回一个新的数组而不是在传入的参数上直接操作,那么在不知道slice的源码的情况下我们也可以大概率的知道

Array.prototype.slice.call(string) //返回一个新数组,成功操作

再同理,mutate的操作sort同样也不行

Array.prototype.sort.call(string) //报错

同理,pop, push, shift, unshift, splice都不行
同理, map, find, forEach 等都可以

Array.prototype.map.call('avb', v => v) // ['a', 'v', 'b']
Array.prototype.pop.call('avb') //报错

不是简单的说“数组的方法当然不能用在字符串上”,数组的方法不过就是一个函数,能不能用要看这个函数内部的实现,如果它的实现和传入的参数是一个字符串不冲突,那么就可以用,反之就不能用,具体问题具体分析

你上面的写法,是让this指向string1,但是你下面写的虽然你想让this指向string1,但这方法不运行你用字符串当参数,你要传一个数组才行。

因为只提供了Array.prototype.slice.call Array.prototype.slice.apply方法,将其字符串切割成一个数组。然后你可以用数组的方法对其进行各种的改变。js没必要封装所有的call和apply

     var string1= 'helloword';
     var a=Array.prototype.slice.call(string1).reverse();//在后面reverse操作
     console.log(a);
     
 var string1= 'helloword';
 var a=Array.prototype.slice.apply(string1).reverse();//在后面reverse操作
 console.log(a);

你这里需要先将这个字符串转化成数组,然后再对这个数组进行逆序处理
var string1= 'helloword';
var a=Array.prototype.slice.call(string1);

 a.reverse();
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题