简体   繁体   中英

How can I reference a primitive type in JavaScript?

I would like to make a function like this work as intended in JavaScript:

function isLastElem(array, elem) {
    if (elem === array[array.length-1]) {
        return true;
    }
    else {
        return false;
    }
}

The intention is that the function should be able to identify the last element of any array. For example:

let arr = [0, 1, 2];
console.log(isLastElem(arr, 2)); // I would expect false to be returned
console.log(isLastElem(arr, arr[2])); // I would expect true to be returned

However, since numbers are primitive values, they are passed to the function by their values and thus both function calls return true. Any way to solve this and pass numbers by reference?

The important idea here would be to make it usable in a for each cycle. For example:

let arr = [0, 1, 0];
arr.forEach((elem) => {
    if (isLastElem(arr, elem)) {
        console.log("Found the last element!");
    }
});

At the first 0 the function should return false, since that is not the last element of the array. Then at the second 0 it should return true and log the message.

You can do this by wrapping your number in an array or object, just like this:

let arr = [[0], [1], [2]];
console.log(isLastElem(arr, [2])); // returns false
console.log(isLastElem(arr, arr[2])); // returns true

Even though I'm struggling to imagine why would anyone ever need to do that, I think we could make this work with Symbol :

Every symbol value returned from Symbol() is unique. A symbol value may be used as an identifier for object properties; this is the data type's only purpose.

So this means we can use Symbol to stamp each element of an array. As you can see an array of 1 s can be converted into an array of symbols of 1 which are all unique:

const xs = [1, 1];

xs[0] === xs[1];
//=> true

const ys = [Symbol(1), Symbol(1)];

ys[0] === ys[1];
//=> false

ys[0] === Symbol(1);
//=> false

ys[1] === ys[1];
//=> true

Therefore to identity the last element of an array, you actually need the reference to that element:

 console.log( [1, 1, 1] // convert to list of symbols of 1 .map(Symbol) // check if current element is equal to the last element .map((x, _, xs) => x === xs[xs.length - 1]) ); //=> [false, false, true]


Of course the problem is that it wraps each element inside a box from which it can't escape.

We can put each element inside an object, hidden behind a "secret unique" key. Each object has a method to extract its value and compare itself with other similar objects:

 const obj = (k, v) => ( { [k]: v , get: () => v , equals: o => o[k] === v }); const stamp = (arr, secret = Date.now()) => arr.map((x, i) => obj(`${secret}@@${i}`, x)); const arr = stamp([1, 1, 1]); arr.forEach((x, _, xs) => { console.log(x.get(), x.equals(xs[xs.length - 1])); });

You could maybe not store the native number, but an instance of Number..

eg.

 function isLastElem(array, elem) { if (elem === array[array.length-1]) { return true; } else { return false; } } let arr = [new Number(0), new Number(1), new Number(2)]; console.log(isLastElem(arr, 2)); // I would expect false to be returned console.log(isLastElem(arr, arr[2])); // I would expect true to be returned

You can try this code


let arr = [0, 1, 2];
console.log(isPrimitive(arr[index+1]));

function isPrimitive(val) {
  return isString(val) || isBoolean(val) || (isNumber(val) && !isNaN(val));
}

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