2016-05-17 4 views
2

Я пытаюсь выяснить, как продлить:Переписать функцию в функции

var outdatedBrowser = function(options) { 
    function startStylesAndEvents() { 
    console.log("bleh"); 
    } 
} 

Я пытаюсь переписать функцию startStylesAndEvents, не касаясь исходный код библиотеки: https://github.com/burocratik/outdated-browser/blob/develop/outdatedbrowser/outdatedbrowser.js

Итак, когда Я называю:

outdatedBrowser({ 
    bgColor: '#f25648', 
    color: '#ffffff', 
    lowerThan: 'transform', 
    languagePath: 'your_path/outdatedbrowser/lang/en.html' 
}) 

и использует функцию startStylesAndEvents, он использует мину вместо у них ...

Спасибо!

ответ

2

Без изменения оригинального источника? Вы не можете.

Все области видимости JavaScript основаны на функциях (без учета let, const и class на данный момент). Если значение объявлено внутри функции, к нему нельзя получить доступ за пределами этой функции, если он не возвращается из функции или не изменяет какое-либо внешнее значение.

Например, представьте себе функцию, как это:

function doStuff() { 
    var times = 10; 
    for (var i = 0; i < times; i++) { 
    doThing(i); 
    } 
} 

Ваш вопрос семантически идентичен с вопросом, как изменить times. Это просто невозможно.

2

Внутренняя функция содержится в закрытии, к которому у вас нет доступа. К сожалению (вопреки идеологии «ничего невозможного») это невозможно сделать во время выполнения.

0

Это то, что вы можете назвать «частной» функцией. Функция хранится так же, как и любая другая переменная. В JavaScript, который обычно означает, что он должен быть «локальной областью» (вместо переменной-члена), поэтому ее нельзя переопределить. (если только они использовали this.functionName ..., тогда вы могли бы переопределить более легко)

Хорошей новостью является наличие взлома, который, похоже, совместим с кросс-браузером. (тестируется в IE 11, с вариантами эмуляции обратно в IE 5!) В JavaScript вы можете заменить фактический «исходный код» самой функции. (Немного отличается от надлежащего переопределения)

var newInnerFunction = function() { // intentionally anonymous for use in eval 
} 
var overriddenFunction = eval(
    outdatedBrowser.toString() // expecting outdatedBrowser to be anonymous for use in eval 
    .replace('{', '{var startStylesAndEvents=' + newInnerFunction.toString() + ';') 
) 

Обратите внимание, что outdatedBrowser является анонимной функцией (просто function()). Если бы он был назван, то использование eval имело бы побочный эффект добавления новой функции в пространство имен под его исходным именем. Дополнительный replace может позаботиться об этом, если это проблема.

0

Скорее всего, вы не можете. Но это не совсем невозможно.

Например, если вы звоните startStylesAndEvents внутри with заявления, сфера действия объекта просочились к внешним

var scope = Object.create(null); 
var outdatedBrowser = function(options) { 
    function startStylesAndEvents() { 
    console.log("bleh"); 
    } 
    with(scope) { 
    startStylesAndEvents(); // You expect this to be the private function above 
    } 
} 
outdatedBrowser(); // "bleh" 

Затем, вы можете угнать вызовы startStylesAndEvents:

scope.startStylesAndEvents = function() { 
    console.log("blah"); 
}; 
outdatedBrowser(); // "blah" 

Не сделайте это, конечно. Это зло, медленно и не допускается в строгом режиме.

+3

К сожалению, для этого требуется «прикосновение к исходному коду библиотеки», которое не будет работать для OP. –

+0

@GeorgeBailey Не обязательно. Вопрос не говорит о том, как библиотека вызывает функцию. Если библиотека вызывает эту функцию внутри оператора 'with', объект области видимости которого просочился наружу, вам не нужно изменять библиотеку. Очень маловероятно, но не невозможно. – Oriol

+0

Я думаю, что OP избегает изменения устаревшего браузера. –