简体   繁体   中英

Why does '.keys' return 'undefined' when applied to the String object in Javascript?

I am trying to understand why the 'keys' method does not return the properties and methods of the String object. In other words what is unique about this object? I tested this theory by creating a generic object, giving it 1 property and 1 method and then running the .keys method on it, and it returned both the property and the method. Since String is an object in Javascript, assumed applying .keys method to it would do the same —at the least returning the .length method in the returned set.

Using Chrome's console I ran the following cases:

typeof String // "function"
"function" == typeof String // true
"object" == typeof String // false

Two notes in addition to my main question: In the scope of JavaScript:

  1. Is a function not an object?
  2. Aren't most things objects outside primitives and some other special cases?

Functions are objects. The defined behavior of typeof is somewhat idiosyncratic. Values in JavaScript are either objects or primitives.

The "keys" property of String instances is undefined because, well, it is not defined on the String prototype. You can add such a property if you like, though working with String instances instead of string primitives is a recipe for lots of weird bugs.

console.log(String)

>function String() { [native code] }

var a = new String()
console.log(a)

>String {length: 0, [[PrimitiveValue]]: ""}

typeof a

>"object"

it should be "class" instead of "function", as like in other languages, but function in js are first-class object (more details here What is meant by 'first class object'? )

object are the instanced classes

Some background information

Effectively Object.keys returns a list of own enumerable properties on the Object instance. These are properties belonging only to that instance of the Object class, excluding any prototypically inherited properties and or methods. These are values that would return true in the following examples:

// Create an Object with own properties
var obj = {
  foo: 'bar'
}

obj.hasOwnProperty('foo') // => true, brilliant

As many will know, this would still hold true when properties are added after the Object has been constructed. As can be seen in this example:

// Create an Object the retroactively add an enumerable property
var obj = {}
obj.foo = 'bar'

obj.hasOwnProperty('foo') // => true, great

Objects, functions, and arrays all behave this way; whereas strings don't. You can easily see this by trying to add own properties to a string and then reading them back, like this:

var str = 'foo'
str.bar = 'baz'

console.log(str)  // => undefined, hmm

// What about "hasOwnProperty"?
str.hasOwnProperty('bar') // => false... too bad

So to answer the question...

Own enumerable properties inherently cannot exist on instances of the String type and cannot be added retrospectively either, because own properties are not assignable to strings, period.

Although this explanation doesn't explain the decisions made whilst implementing this, it certainly gives some underlying sanity as to why String.keys doesn't, or simply can't, exist; and why Object.keys always returns undefined when supplied with a string.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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