Скрытые функции JavaScript? [закрытый]

Исключение нулевого указателя генерируется, когда приложение пытается использовать null в случае, когда требуется объект. К ним относятся:

  1. Вызов метода экземпляра объекта null.
  2. Доступ или изменение поля объекта null.
  3. Принимая длину null, как если бы это был массив.
  4. Доступ или изменение слотов null, как если бы это был массив.
  5. Бросок null как будто это было значение Throwable.

Приложения должны бросать экземпляры этого класса, чтобы указать на другие незаконные использования объекта null.

Ссылка: http://docs.oracle.com/javase/8/docs/api/java/lang/NullPointerException.html

312
задан 11 revs, 6 users 36% 23 May 2017 в 02:10
поделиться

99 ответов

функция l (f, n) {n& & l (f, n-1, f (n));}

л (функция (цикл) {предупреждение (цикл);}, 5);

предупреждения 5, 4, 3, 2, 1

0
ответ дан gbt 23 November 2019 в 01:10
поделиться

Вы можете привязать объект JavaScript как атрибут элемента HTML.

<div id="jsTest">Klick Me</div>
<script type="text/javascript">
    var someVariable = 'I was klicked';
    var divElement = document.getElementById('jsTest');
    // binding function/object or anything as attribute
    divElement.controller = function() { someVariable += '*'; alert('You can change instance data:\n' + someVariable ); };
    var onclickFunct = new Function( 'this.controller();' ); // Works in Firefox and Internet Explorer.
    divElement.onclick = onclickFunct;
</script>
1
ответ дан 23 November 2019 в 01:10
поделиться

Мое первое представление - это не столько скрытая функция, сколько редко используемое приложение функции повторного определения свойства. Поскольку вы можете переопределить методы объекта, вы можете кэшировать результат вызова метода, что полезно, если вычисление является дорогостоящим и вам нужна ленивая оценка. Это дает простейшую форму мемоизации .

function Circle(r) {
    this.setR(r);
}

Circle.prototype = {
  recalcArea: function() {
        this.area=function() {
            area = this.r * this.r * Math.PI;
            this.area = function() {return area;}
            return area;
        }
    },
  setR: function (r) {
      this.r = r;
      this.invalidateR();
    },
  invalidateR: function() {
        this.recalcArea();
    }
}

Реорганизуйте код, который кэширует результат в метод, и вы получите:

Object.prototype.cacheResult = function(name, _get) {
  this[name] = function() {
    var result = _get.apply(this, arguments);
    this[name] = function() {
      return result;
    }
    return result;
  };
};

function Circle(r) {
    this.setR(r);
}

Circle.prototype = {
  recalcArea: function() {
        this.cacheResult('area', function() { return this.r * this.r * Math.PI; });
    },
  setR: function (r) {
      this.r = r;
      this.invalidateR();
    },
  invalidateR: function() {
        this.recalcArea();
    }
}

Если вам нужна мемоизированная функция, вы можете использовать ее вместо этого. Переопределение свойства не требуется.

Object.prototype.memoize = function(name, implementation) {
    this[name] = function() {
        var argStr = Array.toString.call(arguments);
        if (typeof(this[name].memo[argStr]) == 'undefined') {
            this[name].memo[argStr] = implementation.apply(this, arguments);
        }
        return this[name].memo[argStr];
    }
};

Обратите внимание, что это зависит от стандартного преобразования массива в строку и часто не работает должным образом. Его исправление оставлено в качестве упражнения для читателя.

Мое второе задание - геттеры и сеттеры. Я удивлен, что их еще не упомянули. Поскольку официальный стандарт отличается от стандарта де-факто (defineProperty vs. define [GS] etter ) и Internet Explorer почти не поддерживает официальный стандарт, они обычно бесполезны. Может, поэтому их не упомянули. Обратите внимание, что вы можете довольно хорошо комбинировать геттеры и кеширование результатов:

Object.prototype.defineCacher = function(name, _get) {
    this.__defineGetter__(name, function() {
        var result = _get.call(this);
        this.__defineGetter__(name, function() { return result; });
        return result;
    })
};

function Circle(r) {
    this.r = r;
}

Circle.prototype = {
  invalidateR: function() {
        this.recalcArea();
    },
  recalcArea: function() {
        this.defineCacher('area', function() {return this.r * this.r * Math.PI; });
    },
  get r() { return this._r; }
  set r(r) { this._r = r; this.invalidateR(); }
}

var unit = new Circle(1);
unit.area;

Эффективное объединение геттеров, сеттеров и кэширования результатов немного сложнее, потому что вам нужно предотвратить аннулирование или обойтись без автоматического аннулирования при наборе, что и делается в следующем примере. В основном это проблема, если изменение одного свойства приведет к аннулированию нескольких других (представьте, что в этих примерах есть свойство «диаметр»).

Object.prototype.defineRecalcer = function(name, _get) {
  var recalcFunc;
  this[recalcFunc='recalc'+name.toCapitalized()] = function() {
    this.defineCacher(name, _get);
  };
  this[recalcFunc]();
  this.__defineSetter__(name, function(value) {
      _set.call(this, value);
      this.__defineGetter__(name, function() {return value; });
  });
};

function Circle(r) {
    this.defineRecalcer('area',
             function() {return this.r * this.r * Math.PI;},
             function(area) {this._r = Math.sqrt(area / Math.PI);},
    );
    this.r = r;
}

Circle.prototype = {
  invalidateR: function() {
        this.recalcArea();
    },
  get r() { return this._r; }
  set r(r) { this._r = r; this.invalidateR(); }
}
1
ответ дан 23 November 2019 в 01:10
поделиться

Вот простой способ думать об «этом». 'This' внутри функции будет ссылаться на будущие экземпляры объекта функции, обычно созданные с помощью оператора new. Итак, ясно, что «this» внутренней функции никогда не будет относиться к экземпляру внешней функции.

Вышесказанное должно уберечь человека от неприятностей. Но есть более сложные вещи, которые вы можете сделать с этим.


Пример 1:


     function DriveIn()
     {
          this.car = 'Honda';
          alert(this.food);  //'food' is the attribute of a future object 
                             //and DriveIn does not define it.
     }

     var A = {food:'chili', q:DriveIn};  //create object A whose q attribute 
                                         //is the function DriveIn;

     alert(A.car); //displays 'undefined' 
     A.q();        //displays 'chili' but also defines this.car.
     alert(A.car); //displays 'Honda' 


Правило этого:

Всякий раз, когда функция вызывается как атрибут объекта, любое вхождение «this» внутри функции (но вне любых внутренних функций) относится к объекту.

Нам нужно прояснить, что «Правило этого» применяется даже при использовании оператора new. За кулисами new прикрепляет this к объекту через атрибут конструктора объекта.

   
    var C = {constructor:Insect};  //Assign the constructor attribute of C, 
                                   //the value Insect.
    C.constructor();               //Call Insect through the attribute. 
                                   //C is now an Insect instance as though it 
                                   //were created with operator new. [*]
    alert(C.bug);                  //Displays "bee." 
    C.bugFood();                   //Displays "nectar." 

[*] Единственное различие, которое я могу различить, состоит в том, что в примере 3 «конструктор» является перечислимым атрибутом. Когда используется оператор new, «конструктор» становится атрибутом, но не перечисляемым. Атрибут можно перечислить, если операция for-in "for (имя переменной в объекте)" возвращает имя атрибута.

1
ответ дан 23 November 2019 в 01:10
поделиться

Ну, это не особенная функция, но она очень полезна:

Показывает выбираемые и отформатированные предупреждения:

alert(prompt('',something.innerHTML ));
-5
ответ дан 23 November 2019 в 01:10
поделиться

функция может иметь методы.

Я использую этот шаблон отправки форм AJAX.

var fn = (function() {
        var ready = true;
        function fnX() {
            ready = false;
            // AJAX return function
            function Success() {
                ready = true;
            }
            Success();
            return "this is a test";
        }

        fnX.IsReady = function() {
            return ready;
        }
        return fnX;
    })();

    if (fn.IsReady()) {
        fn();
    }
1
ответ дан 23 November 2019 в 01:10
поделиться

Простое самодостаточное кэширование возвращаемого значения функции:

function isRunningLocally(){
    var runningLocally = ....; // Might be an expensive check, check whatever needs to be checked.

    return (isRunningLocally = function(){
        return runningLocally;
    })();
},

Дорогая часть выполняется только при первом вызове, после чего функция только и делает, что возвращает это значение. Конечно, это полезно только для функций, которые всегда возвращают одно и то же значение.

1
ответ дан 23 November 2019 в 01:10
поделиться

Замыкания:

function f() { 
    var a; 
    function closureGet(){ return a; }
    function closureSet(val){ a=val;}
    return [closureGet,closureSet];
}

[closureGet,closureSet]=f(); 
closureSet(5);
alert(closureGet()); // gives 5

closureSet(15);
alert(closureGet()); // gives 15

Замыкание здесь не так называемое деструктурирующее присваивание ( [c, d] = [1,3] эквивалентно ] c = 1; d = 3; ), но тот факт, что вхождения a в closureGet и closureSet по-прежнему относятся к одной и той же переменной. Даже после того, как closureSet присвоил a новое значение!

1
ответ дан 23 November 2019 в 01:10
поделиться

Когда вы пишете обратные вызовы, у вас есть много кода, который будет выглядеть следующим образом:

callback: function(){
  stuff(arg1,arg2);
}

Вы можете использовать функцию ниже, чтобы сделать ее несколько чище.

callback: _(stuff, arg1, arg2) 

Он использует менее известную функцию объекта Function JavaScript, apply.

Здесь также показан другой символ, который можно использовать как имя функции: _.

function _(){
        var func;
        var args = new Array();
        for(var i = 0; i < arguments.length; i++){
                if( i == 0){
                        func = arguments[i];
                } else {
                        args.push(arguments[i]);
                }
        }
        return function(){
                return func.apply(func, args);
        }
}
1
ответ дан 23 November 2019 в 01:10
поделиться