-
Notifications
You must be signed in to change notification settings - Fork 3.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
第 21 题:有以下 3 个判断数组的方法,请分别介绍它们之间的区别和优劣Object.prototype.toString.call() 、 instanceof 以及 Array.isArray() #23
Comments
1. Object.prototype.toString.call()每一个继承 Object 的对象都有 const an = ['Hello','An'];
an.toString(); // "Hello,An"
Object.prototype.toString.call(an); // "[object Array]" 这种方法对于所有基本的数据类型都能进行判断,即使是 null 和 undefined 。 Object.prototype.toString.call('An') // "[object String]"
Object.prototype.toString.call(1) // "[object Number]"
Object.prototype.toString.call(Symbol(1)) // "[object Symbol]"
Object.prototype.toString.call(null) // "[object Null]"
Object.prototype.toString.call(undefined) // "[object Undefined]"
Object.prototype.toString.call(function(){}) // "[object Function]"
Object.prototype.toString.call({name: 'An'}) // "[object Object]"
更多实现可见 谈谈 Object.prototype.toString 2. instanceof
使用 [] instanceof Array; // true 但 [] instanceof Object; // true 3. Array.isArray()
|
从Stack Overflow扒来的资料: |
对于性能问题,我测试几遍的结果 Array.isArray 的性能最好,instanceof 比 toString.call 稍微好了一点点 测试链接: https://jsperf.com/judging-array-type/ 对于其中的性能差异的原理,大家可以讨论一下的 |
arr.constructor === Array |
constructor可以被修改? |
|
const arr = [1, 2]
arr.toString === Object.prototype.toString // false, 所以两者不同,实际上数组上重写了 toString 方法
const o = {o: 1}
o.toString === Object.prototype.toString // true, 所以对象默认不需要如此调用。但如果将对象的方法改写就不一定了
o.toString = function changedToString() {
return 'haha';
}
o.toString() // 'haha'
Object.prototype.toString.call(o) // '[object Object]'. 发现 Object.prototype.toString 也是可以被改写的...
|
typeof 是什么原理呢? |
typeof 只能检测 基本数据类型,包括boolean、undefined、string、number、symbol,而null ,Array、Object ,使用typeof出来都是Objec。无法检测具体是哪种引用类型。 |
想仿写一下Object.prototype.toString,但是卡在了null 和 undefined的判断上,返回[object Window]... ... |
instanceof是判断类型的prototype是否出现在对象的原型链中,但是对象的原型可以随意修改,所以这种判断并不准确。 const obj = {}
obj.__proto__ = Array.prototype
// Object.setPrototypeOf(obj, Array.prototype)
obj instanceof Array // true |
函数的typeof是'function' |
应该要加上 |
typeof不能校验object的其他类型,引用类型除了function都不能区分 instanceof不能校验原始值类型
Object.prototype.toString.call()
|
具体来讲:每一个继承 Object 的对象都有 toString 方法,该方法返回[Object type];Array、function、Date等都继承于Object,但它们都改写了toString方法,所以阻断了对Object原型上toSting方法的调用。 |
我觉得两者说的都没有问题,只是角度不同,对于Object的toString方法来说确实是修改了上下文,而对于Array来说,修改的是调用的toString方法 |
如果遇到精心设计的徦数组怎么判断呢? var fakearray={length:0,__proto__:Array.prototype,[Symbol.toStringTag]:'Array'} var fakearray=Object("fakestring")
fakearray.__proto__=Array.prototype
fakearray[Symbol.toStringTag]='Array' 用 |
如果真数组的 var realarray=[]
realarray[Symbol.toStringTag]='Function'
realarray.__proto__=Function.prototype 用 |
其实还可以用 |
个人感觉题目有必要加上 typeof |
这两个都满足“不可变”性,也就是全局唯一,直接在你的判断函数中用 === 来判断好了,不等于这俩的再去做其他判断。 |
突然很好奇Object下原始toString都干了啥 |
isArray()不是es6新增吗 |
var arr = [1, 2, 3] Array.isArray(arr) // es5新增的 如果不存在可以使用Object.prototype.toString.call(arr) |
2.实际上js在底层存储变量的时候,会在变量的机器码的低位(1-3位)存储其类型信息,对象用的是000,null的所有机器码(不仅是1-3位)都是0,所以typeof还无法区分object 和 null; |
Object.prototype.toString.call()
instanceof虽然 [] instanceof Array 返回true,但是 [] instanceof Object 也是true,说不出有啥缺点 Array.isArray()
各位大佬轻喷😸 |
杠一下,Array.isArray() 在 ES5 就有了,兼容性很好 |
null和undefined不能直接使用toString:Cannot read properties of null/undefined |
那是你没有定义变量.... |
Array.isArray()应该是ES6新增的方法哦 |
这里在理解的时候可能会把Object.prototype.toString.call()与[12].toString()方法相混淆,如果把这两个toString方法当作是一个,那么后续的理解会造成困难。因为当我们期待Object.prototype.toString.call([12])返回一个12时,发现控制台打印的却是【object array】。 |
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/isArray
The text was updated successfully, but these errors were encountered: