break 与 some、every
Personal likes to use forEach
to replace the for
cycle. But sometimes we found the implementation process is required break
. At this point, you have to switch back to the general for
circulation. Meet the following example logic:
let arr = [1, 2, 3, 4, 5]
let text = ''
for (let v of arr) {
if (v === 3) {
break
}
text += v + ','
}
console.log(text) // "1,2,"
复制代码
Today to see the article The thought that since some
the implementation logic itself is short-circuited, that is, upon return true
subsequent iteration is no longer enforced, so why not use some
to replace forEach
it?
let arr = [1, 2, 3, 4, 5]
let text = ''
arr.some(v => {
if (v === 3) {
return true
}
text += v + ','
})
console.log(text) // "1,2,"
复制代码
Under normal circumstances, we some
all use it to return results. And this does not take its return value fuss approach, regarded as a signal of the code to read: it will only use its simple cycle Bale. Of course, so write code readability is not very high. But it is to replace for
one way.
Similarly, every
also a short circuit, of course, may be substituted break
. However, to ensure that break
the previous iteration returns true
:
let arr = [1, 2, 3, 4, 5]
let text = ''
arr.every(v => {
if (v === 3) {
return
}
text += v + ','
return true
})
console.log(text) // "1,2,"
复制代码
This article sent to the circle of friends, friends say this does not look so "pure". We recommended reduce
to achieve, regardless of performance, after all, how many empty iterative performance is not wasted. If you want to replace break
the logic, you have to use a number flag
to achieve, such as:
let arr = [1, 2, 3, 4, 5]
let text = arr.reduce(function(p, c) {
if (this.break) {
return p
}
// ...
if (c === 3) {
this.break = true
return p
}
return p + c + ','
}.bind({}), '')
console.log(text) // "1,2,"
复制代码
Also on "pure", if a function package, the pure:
function formatter(arr) {
let text = ''
arr.some(v => {
if (v === 3) {
return true
}
text += v + ','
})
return text
}
let arr = [1, 2, 3, 4, 5]
console.log(formatter(arr)) // "1,2,"
复制代码
There are also users a message, you can use a recursive way to do it. for
Are recursive loop itself can be replaced. The general break
conditions, just to be a recursive exports. Recursive example of the present example:
function formatter(arr, text = '', i = 0) {
if (arr.length == 0 || arr[i] == '3') {
return text
}
text += arr[i] + ','
return formatter(arr, text, ++i)
}
let arr = [1, 2, 3, 4, 5]
console.log(formatter(arr)) // "1,2,"
复制代码
continue 与 return
As continue
Well. . .
let arr = [1, 2, 3, 4, 5]
let text = ''
for (let v of arr) {
if (v === 3) {
continue
}
text += v + ','
}
console.log(text) // "1,2,4,5,"
复制代码
The answer is simple accident, forEach
directly return
like:
let arr = [1, 2, 3, 4, 5]
let text = ''
arr.forEach(v => {
if (v === 3) {
return
}
text += v + ','
})
console.log(text) // "1,2,4,5,"
复制代码
If continue
and break
exist it? for example:
let arr = [1, 2, 3, 4, 5]
let text = ''
for (let v of arr) {
if (v === 2) {
continue
}
if (v === 4) {
break
}
text += v + ','
}
console.log(text) // "1,3,"
复制代码
Only some
like, anyway array that several API, are in essence for
cycle.
let arr = [1, 2, 3, 4, 5]
let text = ''
arr.some(v => {
if (v === 2) {
return
}
if (v === 4) {
return true
}
text += v + ','
})
console.log(text) // "1,3,"
复制代码
And every place some need to pay attention
some
Array function used to determine whether at least one element satisfies condition callback function. At this time, the callback function may be called a predicate function (i.e., the judgment is not meant). Specification document in some
is so realized:
- Let O be the result of calling ToObject passing the this value as the argument.
- Let lenValue be the result of calling the [[Get]] internal method of O with the argument
"length"
. - Let len be ToUint32(lenValue).
- If IsCallable(callbackfn) is false, throw a TypeError exception.
- If thisArg was supplied, let T be thisArg; else let T be undefined.
- Let k be 0.
- Repeat, while k < len
- Let Pk be ToString(k).
- Let kPresent be the result of calling the [[HasProperty]] internal method of O with argument Pk.
- If kPresent is true, then
- Let kValue be the result of calling the [[Get]] internal method of O with argument Pk.
- Let testResult be the result of calling the [[Call]] internal method of callbackfn with T as the this value and argument list containing kValue, k, and O.
- If ToBoolean(testResult) is true, return true.
- Increase k by 1.
- Return false.
JS analog with its core logic is as follows:
Array.prototype.some = function(callbackfn, thisArg) {
let len = Number(this.length)
let k = 0;
while(k < len) {
let Pk = String(k)
if (Pk in this) {
let kValue = this[Pk]
if (callbackfn.call(thisArg, kValue, k, this)) {
return true
}
}
k++
}
return false
}
复制代码
As can be seen, the callback return value is encountered true
, then the function will return directly to an end. This is the kind of short circuit algorithm, not all callbacks are executed again, and then finally find all the values. every
Is similar, but in contrast, the callback return value is encountered false
, the overall direct return false
of.
Semantic representation from the realization is concerned, some
it is to say: there is a success, I will be successful , but every
is saying: there is a failure, I would have failed .
In addition to stress that can be seen from the realization, when the sparse array index value does not exist, the callback function is not performed. For example, the example callback performed only three times (also other similar API).
let arr = [1, 2, 3]
delete arr[1]
arr[5] = 6
console.log("1" in arr) // false
console.log(arr) // [1, empty, 3, empty × 2, 6]
arr.some(v => {
console.log(v) // 1 3 6
})
复制代码
So empty array, regardless of the callback function to write, the result is still false
:
[].some(_ => true) // false
复制代码
Finished article.
Reproduced in: https: //juejin.im/post/5d08a565e51d45773d468614