Comprender el enlace de JavaScript ()

 

 

 

  • Register!
  • Smart Interface Design Patterns, 10h video + UX training

  • Índice
    1. Lecturas adicionales sobre SmashingMag:
    2. ¿Qué problema realmente buscamos resolver?
      1. ¿Qué acabamos de hacer?
    3. Soporte del navegador
    4. Patrones de uso
      1. Controladores de clic
      2. establecer tiempo de espera
      3. Enlace de eventos más ordenado con querySelectorAll
      4. Conclusión

    La vinculación de funciones es probablemente su menor preocupación al comenzar con JavaScript, pero cuando se da cuenta de que necesita una solución al problema de cómo mantener el contexto de "esto" dentro de otra función, es posible que no se dé cuenta de que lo que realmente necesita es Función. .prototipo.bind().

     

    La vinculación de funciones es probablemente su menor preocupación al comenzar con JavaScript, pero cuando se da cuenta de que necesita una solución al problema de cómo mantener el contexto dentro de thisotra función, es posible que no se dé cuenta de que lo que realmente necesita es Function.prototype.bind().

    Lecturas adicionales sobre SmashingMag:

    • Lo que necesita saber sobre el alcance de JavaScript
    • Una introducción a los eventos DOM
    • 7 cosas de JavaScript que desearía saber mucho antes en mi carrera
    • Cómo escribir JavaScript rápido y con memoria eficiente

    La primera vez que se encuentre con el problema, es posible que se sienta inclinado a establecer thisuna variable a la que pueda hacer referencia cuando cambie de contexto. Mucha gente opta por self, _thiso en ocasiones contextcomo nombre de variable. Todos son utilizables y no hay nada de malo en hacerlo, pero existe una forma mejor y dedicada.

    Jack Archibald tuitea sobre el almacenamiento en caché this:

    Ohhhh, haría cualquier cosa por el alcance, pero no haré eso = esto - Jake Archibald (@jaffathecake) 20 de febrero de 2013

    Debería haber sido más evidente para mí cuando Sindre Sorhus lo explicó en detalle :

    @benhowdle $this para jQuery, para JS simple no lo hago, uso .bind() — Sindre Sorhus (@sindresorhus) 22 de febrero de 2013

     

    Ignoré este sabio consejo durante muchos meses.

    ¿Qué problema realmente buscamos resolver?

    Aquí hay un código de muestra en el que se podría perdonar a alguien por almacenar en caché el contexto en una variable:

    var myObj = { specialFunction: function () { }, anotherSpecialFunction: function () { }, getAsyncData: function (cb) { cb(); }, render: function () { var that = this; this.getAsyncData(function () { that.specialFunction(); that.anotherSpecialFunction(); }); }};myObj.render();

    Si hubiéramos dejado nuestras llamadas a funciones como this.specialFunction(), habríamos recibido el siguiente error:

    Uncaught TypeError: Object [object global] has no method 'specialFunction'

    Necesitamos mantener el contexto del myObjobjeto al que se hace referencia para cuando se llame a la función de devolución de llamada. Llamar that.specialFunction()nos permite mantener ese contexto y ejecutar correctamente nuestra función. Sin embargo, esto podría solucionarse un poco usando Function.prototype.bind().

    Reescribamos nuestro ejemplo:

    render: function () { this.getAsyncData(function () { this.specialFunction(); this.anotherSpecialFunction(); }.bind(this));}

    ¿Qué acabamos de hacer?

    Bueno, .bind()simplemente crea una nueva función que, cuando se llama, tiene su thispalabra clave establecida en el valor proporcionado. Entonces, pasamos nuestro contexto deseado, this(que es myObj), a la .bind()función. Luego, cuando se ejecuta la función de devolución de llamada, thishace referencia myObj.

    Si está interesado en ver cómo Function.prototype.bind()se vería y qué hace internamente, aquí tiene un ejemplo muy simple:

    Function.prototype.bind = function (scope) { var fn = this; return function () { return fn.apply(scope); };}

    Y aquí hay un caso de uso muy simple:

    var foo = { x: 3}var bar = function(){ console.log(this.x);}bar(); // undefinedvar boundFunc = bar.bind(foo);boundFunc(); // 3

    Hemos creado una nueva función que, cuando se ejecuta, se thisestablece en foo, no en el alcance global, como en el ejemplo donde llamamos bar();.

    Soporte del navegador

    Navegador Soporte de versión
    Cromo 7
    Firefox (Geco) 4.0 (2)
    explorador de Internet 9
    Ópera 11.60
    Safari 5.1.4

    Como puede ver, desafortunadamente, Function.prototype.bindno es compatible con Internet Explorer 8 y versiones anteriores, por lo que tendrá problemas si intenta usarlo sin un respaldo. Anime en Español

     

    Afortunadamente, Mozilla Developer Network, siendo el maravilloso recurso que es, proporciona una alternativa sólida si el navegador no ha implementado el .bind()método nativo:

    if (!Function.prototype.bind) { Function.prototype.bind = function (oThis) { if (typeof this !== "function") { // closest thing possible to the ECMAScript 5 internal IsCallable function throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable"); } var aArgs = Array.prototype.slice.call(arguments, 1), fToBind = this, fNOP = function () {}, fBound = function () { return fToBind.apply(this instanceof fNOP oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); }; fNOP.prototype = this.prototype; fBound.prototype = new fNOP(); return fBound; };}

    Patrones de uso

    Cuando aprendo algo, me resulta útil no sólo aprender a fondo el concepto, sino también verlo aplicado a lo que estoy trabajando actualmente (o algo parecido). Con suerte, algunos de los ejemplos siguientes se pueden aplicar a su código o a los problemas que enfrenta.

    Controladores de clic

    Un uso es realizar un seguimiento de los clics (o realizar una acción después de un clic) que podría requerir que almacenemos información en un objeto, así:

    var logger = { x: 0, updateCount: function(){ this.x++; console.log(this.x); }}

    Podríamos asignar controladores de clic como este y posteriormente llamar a updateCount()nuestro loggerobjeto:

    document.querySelector('button').addEventListener('click', function(){ logger.updateCount();});

    Pero hemos tenido que crear una función anónima innecesaria para permitir que la thispalabra clave se mantenga correcta en la updateCount()función.

    Esto podría arreglarse, así:

    document.querySelector('button').addEventListener('click', logger.updateCount.bind(logger));

    Hemos utilizado la .bind()función sutilmente útil para crear una nueva función y luego establecer el alcance que se vinculará al loggerobjeto.

    establecer tiempo de espera

    Si alguna vez ha trabajado con motores de plantillas (como Manillar) o especialmente con ciertos marcos MV* (solo puedo hablar de Backbone.js por experiencia), entonces es posible que esté al tanto del problema que ocurre cuando renderiza la plantilla, pero desea acceder a los nuevos nodos DOM inmediatamente después de su llamada de renderizado.

    Supongamos que intentamos crear una instancia de un complemento jQuery:

    var myView = { template: '/* a template string containing our select / */', $el: $('#content'), afterRender: function () { this.$el.find('select').myPlugin(); }, render: function () { this.$el.html(this.template()); this.afterRender(); }}myView.render();

    Es posible que descubra que funciona, pero no todo el tiempo. Ahí yace el problema. Es una carrera de ratas: lo que suceda para llegar primero, gana. A veces es el renderizado, a veces es la creación de instancias del complemento.

     

    Ahora, sin que algunos lo sepan, podemos usar un ligero truco con setTimeout().

    Con una ligera reescritura, podemos crear una instancia segura de nuestro complemento jQuery una vez que los nodos DOM estén presentes:

    // afterRender: function () { this.$el.find('select').myPlugin(); }, render: function () { this.$el.html(this.template()); setTimeout(this.afterRender, 0); }//

    Sin embargo, recibiremos el mensaje confiable de que .afterRender()no se puede encontrar la función.

    Lo que hacemos, entonces, es añadir nuestro .bind()a la mezcla:

    // afterRender: function () { this.$el.find('select').myPlugin(); }, render: function () { this.$el.html(this.template()); setTimeout(this.afterRender.bind(this), 0); }//

    Ahora, nuestra afterRender()función se ejecutará en el contexto correcto.

    Enlace de eventos más ordenado con querySelectorAll

    La API DOM mejoró significativamente una vez que incluyó métodos tan útiles como querySelectory querySelectorAllla classListAPI, por nombrar algunos de los muchos.

    Sin embargo, todavía no existe una forma de agregar eventos de forma nativa NodeList. Entonces, terminamos robando la forEachfunción del Array.prototypebucle to, así:

    Array.prototype.forEach.call(document.querySelectorAll('.klasses'), function(el){ el.addEventListener('click', someFunction);});

    Sin embargo, podemos hacerlo mejor que eso con nuestro amigo .bind():

    var unboundForEach = Array.prototype.forEach, forEach = Function.prototype.call.bind(unboundForEach);forEach(document.querySelectorAll('.klasses'), function (el) { el.addEventListener('click', someFunction);});

    Ahora tenemos un método ordenado para recorrer nuestros nodos DOM.

    Conclusión

    Como puede ver, la ()función de vinculación de JavaScript se puede incluir sutilmente para muchos propósitos diferentes, así como para ordenar el código existente. Esperamos que esta descripción general le haya brindado lo que necesita agregar .bind()a su propio código (¡si es necesario!) y aprovechar el poder de transformar el valor de this.

    (un poco)Explora más en

    • Codificación
    • Herramientas
    • javascript
    • Técnicas





    Tal vez te puede interesar:

    1. ¿Deberían abrirse los enlaces en ventanas nuevas?
    2. 24 excelentes tutoriales de AJAX
    3. 70 técnicas nuevas y útiles de AJAX y JavaScript
    4. Más de 45 excelentes recursos y repositorios de fragmentos de código

    Comprender el enlace de JavaScript ()

    Comprender el enlace de JavaScript ()

    Register! Smart Interface Design Patterns, 10h video + UX training Índice Lecturas adicionales sobre Smas

    programar

    es

    https://pseint.es/static/images/programar-comprender-el-enlace-de-javascript--836-0.jpg

    2024-04-04

     

    Comprender el enlace de JavaScript ()
    Comprender el enlace de JavaScript ()

    Si crees que alguno de los contenidos (texto, imagenes o multimedia) en esta página infringe tus derechos relativos a propiedad intelectual, marcas registradas o cualquier otro de tus derechos, por favor ponte en contacto con nosotros en el mail [email protected] y retiraremos este contenido inmediatamente

     

     

    Top 20