Страницы

Поиск по вопросам

Показаны сообщения с ярлыком prototype. Показать все сообщения
Показаны сообщения с ярлыком prototype. Показать все сообщения

вторник, 25 февраля 2020 г.

Чем отличается код javascript?

#prototype #javascript

Объясните пожалуйста, кто знает, чем отличается этот код:
function Button() {
  this.cc = 0;
  this.clicked = function() {
    this.cc+=1;
    console.log('Clicked ' + this.cc);
  }
}

От вот этого:
 function Button() {
      this.cc = 0;
    }
    Button.prototype.clicked = function() {
      this.cc+=1;
      console.log('Clicked ' + this.cc);
    }
    


Ответы

Ответ 1



Внешне - ничем не отличает. Но внутренне, для случая: function Button() { this.cc = 0; this.clicked = function() { cc+=1; console.log('Clicked ' + this.cc); } } (new Button()).clicked != (new Button()).clicked И это реально разные ( почти всегда полностью ) функции, с разным контекстом исполнения, и т.д и т.п... P.S: В принципи, это можно назвать private свойствами: function Button(){ var obj_private = {}, obj_fn = [], obj = this; for( var fn in this ){ if ( typeof this[ fn ] === 'function' ){ obj_fn.push( this[ fn ] ); } } this.get_private = function (){ if ( ( this == obj ) && ( obj_fn.indexOf( arguments.caller.callee ) != -1 ) ){ return private_obj; } } } Button.prototype.clicked = function (){ var pr = this.get_private(); pr[ cc ]++; console.log( 'Clicked' + pr[ cc ] ); }

Ответ 2



Первое - создание одного объекта, инициализация у него свойства и добавление к нему одного метода. Второе - создание одного объекта, инициализация у него свойства и добавление метода к прототипу, то есть ко всем объектам этого типа. (То есть разница в том, что у других объектов этого типа в первом случае нового метода clicked не будет, а во втором - будет.)

пятница, 24 января 2020 г.

добавление функционала в Javascript (поиск в массиве), не поддерживаемого IE

#javascript #функции #internet_explorer #prototype #совместимость

Приветствую

Использую для поиска в массиве метод Array.prototype.find()

var dialogNode = xml.find(function(element){
    var objectParams = myGetTagParams(element.nodeName);

    return (objectParams.type == 'my:dialog');
});


но в IE этот функционал не поддерживается :( (а IE используют некоторые пользователи
сайта)

поэтому для них пришлось переписать код

var dialogNode = '';

for (var index in xml)
{
    var element = xml[index];

    var objectParams = myGetTagParams(element.nodeName);

    if (objectParams.type == 'my:dialog')
    {
        dialogNode = element;
        break;
    }
}


Это не очень удобно, когда в разных частях сайта используются конструкции типа "если
у пользователя один браузер - выполняй это, а если другой - выполняй это"

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

if (Array.prototype.find == undefined)
    Array.prototype.find = function(){}


?

И тогда смело в любом месте сайта можно вызывать функционал одним и тем же способом,
хотя код для разных браузеров будет различным
    


Ответы

Ответ 1



Кажется разобрался! Главное - если прототипа не существовало, приходится внедрять его несколько иным путём, чем показано в приведённых в вопросе примерах, а именно использовать Object.defineProperty: if (!Array.prototype.find) { Object.defineProperty(Array.prototype, "find", { value: function(predicate) { if (this == null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof predicate !== 'function') { throw new TypeError('predicate must be a function'); } var list = Object(this); var length = list.length >>> 0; var thisArg = arguments[1]; var value; for (var i = 0; i < length; i++) { value = list[i]; if (predicate.call(thisArg, value, i, list)) { return value; } } return undefined; }, }); }

понедельник, 6 января 2020 г.

Добавление метода к объекту через прототип

#javascript #prototype

Приведённый ниже код должен назначить объекту типа Image с помощью прототипа три
новых метода: protocol(), host() и pathname().
В браузере FireFox всё проходит нормально. Chrome выдаёт следующую ошибку:


  Uncaught TypeError: document.i1.protocol is not a function


Соответственно, и остальные функции document.i1.host и document.i1.path не выполняются.  

В чём заключается проблема, и как её решить?

function pr() {
    a = this.src.split(':');
    return a[0] + ':';
}

function ho() {
    a = this.src.split(':');
    path = a[1].split('/');
    return path[2];
}

function pa() {
    path = this.src.split('/');
    path[0] = '';
    path[2] = '';
    return path.join('/').split('///').join('/');
}

Image.prototype.protocol = pr;
Image.prototype.host = ho;
Image.prototype.pathname = pa;

document.write("
"); document.write(document.i1.src + "
"); document.write(document.i1.protocol() + "
"); document.write(document.i1.host() + "
"); document.write(document.i1.pathname() + "
");


Ответы

Ответ 1



Полученный (например, с помощью document.getElementById('img') или new Image()) имеет тип HTMLImageElement. Соответственно, добавлять новые методы нужно именно в его прототип. Пример: function log(info) { document.body.innerHTML += info + "
"; } HTMLImageElement.prototype.protocol = function() { log("Protocol is called"); }; var img = document.getElementById('img'); log("Got image: " + img.constructor.name); img.protocol(); var newImage = new Image(); log("New image: " + newImage.constructor.name); newImage.protocol();


Ответ 2



function pr() { a = this.src.split(':'); return a[0] + ':'; } function ho() { a = this.src.split(':'); path = a[1].split('/'); return path[2]; } function pa() { path = this.src.split('/'); path[0] = ''; path[2] = ''; return path.join('/').split('///').join('/'); } Image.prototype.protocol = pr; Image.prototype.host = ho; Image.prototype.pathname = pa; var out = document.getElementById("out"), i1, html; out.innerHTML = "
"; i1 = document.getElementById('i1'); html = out.innerHTML; html += "src: " + i1.src + "
"; html += "protocol: " + i1.protocol() + "
"; html += "host: " + i1.host() + "
"; html += "pathname: " + i1.pathname() + "
"; out.innerHTML = html;
Вероятно, вы несколько раз выполнили скрипт на странице, и появилось несколько элементов с именем "i1", поэтому в последующи разы нужно было бы обращаться к document.i1[0].protocol(). Лучше сделать так: document.write("
"); var i1 = document.getElementById('i1'); document.write(i1.src+"
"); document.write(i1.protocol()+"
"); ...

Ответ 3



Вот рабочий вариант. Спасибо @Regent и @Sergiks и @Grundy
Got image: HTMLImageElement
: