동적 실행 스 크 립 트

11786 단어 NodeJS
동적 실행 스 크 립 트 를 언급 하면 여러분 이 생각 하 는 것 은 eval 또는 new Function() 입 니 다. nodejs 에 전속 vm 모듈 이 있어 서 해당 하 는 Sandbox 역할 을 완성 할 수 있 습 니 다.
브 라 우 저 에서 동적 실행 스 크 립 트eval()
함 수 는 들 어 오 는 문자열 을 자 바스 크 립 트 코드 로 실행 하고 문자열 에 있 는 코드 의 반환 값 을 되 돌려 줍 니 다.인자 가 문자열 이 아니라면 그대로 되 돌려 줍 니 다.
만약 당신 이 간접 적 으로 eval() 를 사용한다 면, 예 를 들 어 하나의 인용 을 통 해 그것 을 호출 하 는 것 이지, 직접적인 호출 이 아니다 eval.ECMAScript 5 에서 시작 하여 국부 적 역할 영역 이 아 닌 전역 적 역할 영역 에서 작 동 합 니 다.
function test() {
  let x = 2, y = 4;
  console.log(eval('x + y'));  //     ,       ,    6
  let geval = eval; //            
  console.log(geval('x + y')); //     ,       ,throws ReferenceError   `x`   
  (0, eval)('x + y'); //           
}
eval 에서 함수 가 문자열 로 정의 되 려 면 접두사 와 접두사 로 '(' 와 ')' 가 필요 합 니 다.
let fctStr1 = 'function a() {}'
let fctStr2 = '(function a() {})'
let fct1 = eval(fctStr1)  //   undefined
let fct2 = eval(fctStr2)  //       

MDN 은 eval 을 영원히 사용 하지 말 것 을 권장 합 니 다.
  • eval() 호출 자 와 같은 권한 실행 코드 를 사용 합 니 다.만약 당신 이 eval() 실행 중인 문자열 코드 가 악성 코드 (호의 가 없 는 사람) 에 의 해 수정 된다 면, 당신 은 최종 적 으로 웹 페이지 / 확장 프로그램의 권한 하에 사용자 컴퓨터 에서 악성 코드 를 실행 할 수 있 습 니 다.더 중요 한 것 은 제3자 코드 는 특정한 eval() 이 호출 될 때의 역할 도 메 인 을 볼 수 있 고 서로 다른 방식 의 공격 을 초래 할 수도 있다.
  • eval() 는 보통 다른 대체 방법 보다 더 느리다. 왜냐하면 JS 해석 기 를 호출 해 야 하고 많은 다른 구 조 는 현대 JS 엔진 에 의 해 최적화 될 수 있 기 때문이다.이 밖 에 현대 자 바스 크 립 트 해석 기 는 자 바스 크 립 트 를 기계 코드 로 변환 했다.이것 은 모든 변수 이름 의 개념 이 삭 제 될 것 임 을 의미한다.따라서 임의의 eval 사용 은 브 라 우 저 에 게 지루 한 변수 이름 을 찾 도록 강요 하여 변수 가 기계 코드 에 있 는 위 치 를 확인 하고 값 을 설정 합 니 다.

  • Function 은 eval 을 대체 하 는 좋 은 방법 이다.
    Function
    new Function ([arg1[, arg2[, ...argN]],] functionBody)
    

    모든 자 바스 크 립 트 함 수 는 사실상 하나의 Function 대상 이다.운행 (function(){}).constructor === Function // true 하면 이 결론 을 얻 을 수 있다.eval 와 달리 Function 생 성 된 함 수 는 전체 역할 영역 에서 만 실 행 될 수 있 습 니 다.
    function test() {
      let x = 2, y = 4;
      console.log(new Function('return x + y')());  //     ,       ,throws ReferenceError
    }
    

    Nodejs 동적 실행 스 크 립 트
    node 의 핵심 모듈 vm 를 통 해 이 루어 집 니 다.vm 는 v8 의 Virtual Machine contexts 를 사용 하여 코드 를 동적 으로 컴 파일 하고 실행 할 수 있 으 며, 코드 의 실행 컨 텍스트 는 현재 프로 세 스 와 격 리 되 어 있 습 니 다. 그러나 이곳 의 격 리 는 절대적 인 안전 이 아니 라 브 라 우 저의 샌 드 박스 환경 과 완전히 같 지 않 습 니 다.
  • vm.runInContext(code, contextifiedObject[, options]) 지정 한 contextifiedObject 컨 텍스트 에서 이 를 실행 하고 결 과 를 되 돌려 줍 니 다.실 행 된 코드 는 로 컬 역할 영역 을 가 져 올 수 없습니다.contextifiedObject 사전에 vm.createContext() 방법 으로 문맥 이 격 리 된 대상 이 어야 한다.
    const vm = require('vm')
    
    const contextObject = { a: 1 }
    vm.createContext(contextObject)
    const result = vm.runInContext('a += 1; b = 3', contextObject)
    console.log(result) // 3 { a: 2, b: 3 }
    
  • vm.runInNewContext(code[, contextObject[, options]]) 지정 한 contextObject undefined 에 게 격 리 된 컨 텍스트 를 제공 하고 이 컨 텍스트 에서 컴 파일 된 contextObject 을 실행 하여 결 과 를 되 돌려 줍 니 다.실행 중인 코드 는 로 컬 역할 영역 을 가 져 올 수 없습니다.
    const vm = require('vm')
    
    const result = vm.runInNewContext('a += 1; b = 3', {a: 1})
    console.log(result)	// 3 { a: 2, b: 3 }
    
  • code 현재 vm.runInThisContext(code[, options]) 대상 의 문맥 에서 컴 파일 하고 실행 global 한 다음 에 결 과 를 되 돌려 줍 니 다.실행 중인 코드 는 로 컬 역할 영역 을 가 져 올 수 없 지만 현재 code 대상 을 가 져 올 수 있 습 니 다.
    global.a = 1
    const result = vm.runInThisContext('a += 1')
    console.log(result)
    
    global 는 간접 적 인 집행 vm.runInThisContext() 과 비슷 하 다 eval().
  • (0,eval)('code') Nodejs 에서 도 eval 함 수 를 사용 할 수 있 지만 성능 과 안전성 에 차이 가 있다.확인 하 세 요.https://odino.org/eval-no-more-understanding-vm-vm2-nodejs/
  • vm2 Node. js 의 고급 vm / sandbox,https://github.com/patriksimek/vm2

  • 문맥 격 리 화
    Node. js 로 실행 되 는 모든 JavaScript 코드 는 '컨 텍스트' 의 역할 영역 에서 실 행 됩 니 다.V8 에서 하나의 컨 텍스트 는 실행 환경 입 니 다. 분 리 를 허용 합 니 다. 무관 한 자바 스 크 립 트 는 V8 의 단일 예 에서 실 행 됩 니 다.모든 자 바스 크 립 트 코드 를 실행 할 상하 문 을 명확 하 게 지정 해 야 합 니 다.
    vm.createContext([contextObject[, options]])
    
    eval() 인자 contextObjectcontextObject 이면 새로 만 든 대상) 는 내부 에서 V8 컨 텍스트 의 새로운 인 스 턴 스 와 연 결 됩 니 다.이 V8 컨 텍스트 는 undefined 모듈 을 사용 하 는 방법 으로 실행 되 는 vm 과 그 중에서 실행 가능 한 격 리 된 전역 환경 을 제공 합 니 다.
    필드 사용
    동적 실행 문자열 코드.vue ssr 에 서 는 runInNewContext 를 통 해 이 루어 집 니 다 (Vue SSR 지침).
    참조 주소
  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
  • http://nodejs.cn/api/vm.html
  • https://ssr.vuejs.org/zh/api/#runinnewcontext
  • https://odino.org/eval-no-more-understanding-vm-vm2-nodejs/
  • https://github.com/patriksimek/vm2
  • 좋은 웹페이지 즐겨찾기