Thanks for the answers from Tim Pietzcker and other persons. I was so inspired by their works. However, there is no any ideal solution, I think, for mimicking lookbehind. For example, solution from Pietzcker is limited by $ as EOL, that is, without $ there would get unexpected result:
let str="filename.js  main.js  2022.07.01"
console.log( /^(?!.*filename\.js).*\.js/g.exec(str) ) //null
Another limitation is that it is hard to translate multiply lookbehinds, such as:
let reg=/(?<!exP0)exp0 \d (?<!exP1)exp1 \d (?<!exP2)exp2/
How to build a more generic and free method to use lookbehind assertion alternatively? Bellow is my solution.
The core pattern of alternative code is:
(?:(?!ExpB)....|^.{0,3})ExpA <= (?<!ExpB)ExpA
Detail explanation:
(?:         # start an unsave group:
 (?!ExpB)   # Assert a possion who can't match the ExpB
 ....       # Any string, the same length as ExpB
 |^.{0,3}   # Or match any string whoes length is less than ExpB
)           # End of negative lookahead
ExpA        # Match ExpA
For instance:
var str="file.js  main.js  2022.07.01"
var reg=/(?:(?!file)....|^.{0,3})\.js/g // <= (?<!file)\.js
console.log( reg.exec(str)[0] )  // main.js
Here is an implement to translate above pattern into a sugar:
var str="file.js  main.js  2022.07.01"
var reg=newReg("﹤4?!file﹥\\.js","g") //pattern sugar
console.log(reg.exec(str)[0]) // main.js
function newReg(sReg,flags){
  flags=flags||""
  sReg=sReg.replace(/(^|[^\\])\\﹤/g,"$1<_sl_>").replace(/(^|[^\\])\\﹥/g,"$1<_sr_>")
  if (/﹤\?<?([=!])(.+?)﹥/.test(sReg)){
    throw "invalid format of string for lookbehind regExp"
  }
  var reg=/﹤(\d+)\?<?([=!])(.+?)﹥/g
  if (sReg.match(reg)){
    sReg=sReg.replace(reg, function(p0,p1,p2,p3){
      return "(?:(?"+p2+p3+")"+".".repeat(parseInt(p1))+"|^.{0,"+(parseInt(p1)-1)+"})"
    })
  }
  sReg=sReg.replace(/<_sl_>/g,"﹤").replace(/<_sr_>/g,"﹥")
  var rr=new RegExp(sReg,flags)
  return rr
}
Two special characters  ﹤( \uFE64 or ﹤ ) and ﹥ ( \uFE65 or ﹥ )  are used to enclose the lookbehind expression, and a number N counting the length of lookbehind expression must follow the ﹤. That is ,the syntax of lookbehind is:
﹤N?!ExpB﹥ExpA <= (?<!ExpB)ExpA
﹤N?=ExpB﹥ExpA <= (?<=ExpB)ExpA
To make the pattern above more ES5-like, you can replace ﹤ or ﹥ with parenthesis and remove N , by writing more code into newReg() function.