Tôi có thể tắt chế độ nghiêm ngặt ECMAscript cho các chức năng cụ thể không?


78

Tôi không tìm thấy bất kỳ điều gì về câu hỏi của mình ở đây trên MDC hoặc thông số kỹ thuật ECMAscript. Có lẽ ai đó biết một cách 'hacky' hơn để giải quyết vấn đề này.

Tôi đang gọi "use strict"mọi tệp javascript trong môi trường của mình. Tất cả các tệp của tôi bắt đầu như thế này

(function(win, doc, undef) {
    "use strict";

    // code & functions
}(window, window.document));

Bây giờ, tôi có một chức năng tùy chỉnh để xử lý lỗi. Các hàm đó sử dụng thuộc .callertính để cung cấp dấu vết ngăn xếp ngữ cảnh . Trông như thế này:

var chain = (function() {
    var _parent = _error,
        _ret = '';

    while( _parent.caller ) {
        _ret += ' -> ' + _parent.caller.name;
        _parent = _parent.caller;
    }

    return _ret;
}());

Nhưng tất nhiên, ở chế độ nghiêm ngặt .callerlà một phần mềm hỗ trợ không thể xóa được sẽ ném khi được truy xuất. Vì vậy, câu hỏi của tôi là, có ai biết cách vô hiệu hóa "chức năng khôn ngoan" nghiêm ngặt hơn không?

"use strict";được kế thừa bởi tất cả các hàm sau khi nó được gọi. Bây giờ chúng ta có khả năng chỉ sử dụng chế độ nghiêm ngặt trong các chức năng cụ thể bằng cách chỉ gọi "use strict";ở trên cùng của chúng, nhưng có cách nào để đạt được điều ngược lại không?


Bạn có thể hack nó bằng đánh giá toàn cầu để bỏ qua chế độ nghiêm ngặt
Raynos

1
Trong trường hợp khác cần phải biết điều này là tất cả về: Có gì không sử dụng nghiêm ngặt làm
mplungjan

Tôi gần như hy vọng một cái gì đó như thế này không tồn tại. Ý tưởng "sử dụng nghiêm ngặt" là một chiến lược chọn tham gia để tương thích ngược. Tôi không chắc mình thích ý tưởng về khả năng tương thích ngược-xuôi, nơi chúng tôi cho phép mã chọn tham gia và sau đó cho phép các phần nhỏ của mã chọn không tham gia lại.
davin

bạn có thể xem tại đây >> chỉ cần thay đổi giải pháp .babelrc
hisland

Câu trả lời:


88

Không, bạn không thể tắt chế độ nghiêm ngặt cho mỗi chức năng.

Điều quan trọng là phải hiểu rằng chế độ nghiêm ngặt hoạt động theo từ vựng ; ý nghĩa - nó ảnh hưởng đến khai báo hàm, không ảnh hưởng đến việc thực thi. Bất kỳ hàm nào được khai báo trong mã nghiêm ngặt sẽ trở thành một hàm nghiêm ngặt. Nhưng không phải bất kỳ hàm nào được gọi từ trong mã nghiêm ngặt cũng nhất thiết phải nghiêm ngặt:

(function(sloppy) {
  "use strict";

   function strict() {
     // this function is strict, as it is _declared_ within strict code
   }

   strict();
   sloppy();

})(sloppy);

function sloppy(){
  // this function is not strict as it is _declared outside_ of strict code
}

Lưu ý cách chúng ta có thể xác định hàm bên ngoài mã nghiêm ngặt và sau đó chuyển nó vào hàm nghiêm ngặt.

Bạn có thể làm điều gì đó tương tự trong ví dụ của mình - có một đối tượng có các hàm "cẩu thả", sau đó chuyển đối tượng đó đến hàm được gọi ngay lập tức nghiêm ngặt đó. Tất nhiên, điều đó sẽ không hoạt động nếu các hàm "cẩu thả" cần tham chiếu đến các biến từ bên trong hàm wrapper chính.

Cũng lưu ý rằng đánh giá gián tiếp - do người khác đề xuất - sẽ không thực sự hữu ích ở đây. Tất cả những gì nó làm là thực thi mã trong ngữ cảnh toàn cầu. Nếu bạn cố gắng gọi một hàm được xác định cục bộ, thì hàm eval gián tiếp thậm chí sẽ không tìm thấy nó:

(function(){
  "use strict";

  function whichDoesSomethingNaughty(){ /* ... */ }

  // ReferenceError as function is not globally accessible
  // and indirect eval obviously tries to "find" it in global scope
  (1,eval)('whichDoesSomethingNaughty')();

})();

Sự nhầm lẫn này về đánh giá toàn cục có thể xuất phát từ thực tế là đánh giá toàn cục có thể được sử dụng để truy cập vào đối tượng toàn cầu từ bên trong chế độ nghiêm ngặt (không chỉ đơn giản là có thể truy cập thông qua thisnữa):

(function(){
  "use strict";

  this; // undefined
  (1,eval)('this'); // global object
})();

Nhưng quay lại câu hỏi ...

Bạn có thể gian lận và khai báo một hàm mới thông qua hàm Functiontạo - điều này xảy ra không kế thừa tính nghiêm ngặt, nhưng điều đó sẽ dựa vào việc dịch ngược hàm (không chuẩn) và bạn sẽ mất khả năng tham chiếu các biến bên ngoài .

(function(){
  "use strict";

  function strict(){ /* ... */ }

  // compile new function from the string representation of another one
  var sneaky = Function('return (' + strict + ')()');

  sneaky();
})();

Lưu ý rằng FF4 + dường như không đồng ý với thông số kỹ thuật (theo những gì tôi có thể nói) và đánh dấu sai chức năng được tạo thông qua Functionlà nghiêm ngặt. Điều này không xảy ra trong các triển khai hỗ trợ chế độ nghiêm ngặt khác (như Chrome 12+, IE10, WebKit).


Làm thế nào để truyền đối số cho hàm lén lút?
Szymon Toda

Cảm ơn, tôi đã gặp một vấn đề xấu trong bài kiểm tra đơn vị jasmine cần sửa đổi một biến toàn cục được sử dụng bởi lớp đang kiểm tra và tôi không thể làm được. Ăn gian tuyệt vời!
Juangui Jordán

@kangax, Nếu tôi đang sử dụng chế độ nghiêm ngặt, nhưng tôi muốn tắt nó theo cách động. tức là, tôi đang khai báo một hàm là nghiêm ngặt nhưng trong một số trường hợp, tôi không muốn hàm đó nghiêm ngặt và tôi muốn thay đổi hàm thành không nghiêm ngặt. Tôi phải làm gì.?
Jeyanth

3

Một giải pháp thay thế chỉ đơn giản là làm điều này

var stack;
if (console && console.trace) {
     stack = console.trace();
} else {
    try {
        var fail = 1 / 0;
    } catch (e) {
        if (e.stack) {
            stack = e.stack;
        } else if (e.stacktrace) {
            stack = e.stacktrace;
        }
    }
}
// have fun implementing normalize.
return normalize(stack);

3

(Từ http://javascriptweblog.wordpress.com/2011/05/03/javascript-strict-mode/ )

(...) Chế độ nghiêm ngặt không được thực thi trên các hàm không nghiêm ngặt được gọi bên trong phần thân của một hàm nghiêm ngặt (vì chúng đã được chuyển dưới dạng đối số hoặc được gọi bằng cách sử dụng callhoặc apply).

Vì vậy, nếu bạn thiết lập các phương thức lỗi trong một tệp khác, không có chế độ nghiêm ngặt, rồi chuyển chúng dưới dạng tham số, như sau:

var test = function(fn) {
  'use strict';
  fn();
}

var deleteNonConfigurable = function () {
  var obj = {};
  Object.defineProperty(obj, "name", {
    configurable: false
  });
  delete obj.name; //will throw TypeError in Strict Mode
}

test(deleteNonConfigurable); //no error (Strict Mode not enforced)

... nó sẽ hoạt động.


dường như không hiệu quả với tôi trong FF4. Tôi đã xóa hoàn toàn các hướng dẫn nghiêm ngặt trên tệp và đó là phương pháp chứa phương pháp xử lý lỗi. Tôi sẽ vẫn nhận lỗi nghiêm ngặt.
jAndy
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.