js中的前期绑定,后期绑定以及问题

javascript 的函数在执行期间才会确定他的context,也就是说this在此时被赋值。

但是你常常遇到这种情况

function process(){

this.name = "hello";

document.onclick = function(){

alert(this.name);

}

}

var  p = new process();

-------------------------------------

上面这个 程序执行之后,你在页面上“点击”,你期待出现的是 “hello”,实际的结果是 undefined;

1问题来了,this.name 怎么会没定义呢,  仔细看下发现 ,点击时,执行了函数 那么此时的context是什么呢,this 自然就是document,但是document没有name属性,自然就是没定义了。

2 你期待的结果是什么呢   弹出 “hello”

怎么解决呢

(1)既然执行函数时this赋值,我们不使用this 不就完了

function process(){

var self = this;

this.name = "hello";

document.onclick = function(){

alert(self.name);

}

(2) 还想使用this     ES5 中使用了一个bind方法,可以实现这个

document.onclick = function(){

alert(this.name);

            }.bind(this);

但是这里有个问题,就是bind 函数只能针对 expression的函数声明,对于declaration的 没有此函数

并且并不是所有的浏览器都支持这个方法。

跨浏览器的做法

        Function.prototype.bind = Function.prototype.bind || function(th){

            var func = this;

            return function(){

                func.apply(th,[].slice.call(arguments));

            }

        }

(3) 还有一种方法,我们可以利用一个工具函数,专门的导入这个this,保持this的上下文一致

        function fixThis(func,th){

            return function(){

                return func.apply(th);           

            }

        }

上面的点击可以写成

            document.onclick = fixThis(function(){

                alert(this.name);

            },this);

----------------------------------------

早期绑定有个问题是,当你遇到继承的情况

        function preBind(func,th){

            return function(){

                func.apply(th,[].slice.call(arguments));

            }

        }

        function Animal(){

            this.type = function(){

                alert("Animal");

            }

          document.onclick = preBind(this.type,this); 

    

        }

        function Cat(){

            Animal.call(this);//继承 Animal

            this.type = function(){

                alert("cat");

            }

        }

//执行

new Cat();

你期待的结果是,点击之后,出现“cat”  但是实际的结果是 “Animal”,问题出在哪里呢

问题出在这里   document.onclick = preBind(this.type,this);      这个函数是在 Animal 里面注册的,

当 继承时,即执行preBind() 函数,返回一个闭包,此闭包的环境hold住的弹出内容的方法体是 “Animal"那个

如何解决呢,  把早期绑定的内容 换成,下面这个,后期绑定,执行时根据具体的环境决定那个函数被调用。

        function postBind(str,th){

            return function(){

                return th[str].apply(th,[].slice.call(arguments));

            }

        }

时间: 2024-08-11 09:43:28

js中的前期绑定,后期绑定以及问题的相关文章

关于JAVA中的前期绑定 后期绑定(动态绑定)

前期绑定,在程序执行前根据编译时类型绑定,调用开销较小,如C语言只有前期绑定这种方法调用. 后期绑定,是指在运行时根据对象的类型进行绑定,又叫动态绑定或运行时绑定.实现后期绑定,需要某种机制支持,以便在运行时能判断对象的类型,调用开销比前期绑定大. Java中的static方法和final方法(private属于final方法,详细的解释见<Java编程思想>)属于前期绑定,子类无法重写final方法,成员变量(包括静态及非静态)也属于前期绑定.除了static方法和final方法(priva

JS中this的4种绑定规则

this ES6中的箭头函数采用的是词法作用域. 为什么要使用this:使API设计得更简洁且易于复用. this即不指向自身,也不指向函数的词法作用域. this的指向只取决于函数的调用方式 this绑定规则 new > 显示绑定 > 隐式绑定 > 默认绑定 默认绑定 当独立函数调用时,不管是否在调用栈中,this都指向全局对象(浏览器中为window) 严格模式下,不能将全局对象用于默认绑定. var a = 2; function foo(){ console.log(this.a

js中关于事件处理函数名后面是否带括号的问题

今天总结一个关于事件处理程序的小细节.首先回顾一下事件处理的一些概念. JS中的事件处理(事件绑定)就是让某种或某些事件触发某些活动.有两种常见的形式,分别是DOM Level 0 和DOM Level 2.这两种方式最大的区别就在于DOM 0级事件处理只能用于事件冒泡,而DOM 2级事件处理却可以通过设置第三个参数来分别支持事件冒泡和事件捕获. DOM 0级事件处理一般是直接把一个函数分配给一个事件处理程序,既可以在元素中直接分配一个事件处理程序,如方式一所示;也可以在脚本中把函数分配给事件处

前期绑定和后期绑定

程序绑定的概念:绑定指的是一个方法的调用与方法所在的类(方法主体)关联起来.对java来说,绑定分为静态绑定和动态绑定:或者叫做前期绑定和后期绑定 静态绑定:在程序执行前方法已经被绑定,此时由编译器或其它连接程序实现.例如:C.针对java简单的可以理解为程序编译期的绑定:这里特别说明一点,java当中的方法只有final,static,private和构造方法是前期绑定 动态绑定:后期绑定:在运行时根据具体对象的类型进行绑定.若一种语言实现了后期绑定,同时必 须提供一些机制,可在运行期间判断对

angular.js 中同步视图和模型数据双向绑定,$watch $digest $apply 机制

Angular.js 中的特性,双向绑定. 让视图的改变直接反应到数据中,数据的改变又实时的通知到视图,如何做到的? 这要归功于 scope 下面3个重要的方法: $watch $digest $apply 他们的区别是什么,我们来介绍下: $watch 这是一个监听 scope 上数据的监听器 方法说明: $scope.$watch('参数',function(newValue,oldValue){ //逻辑处理 }) 上面我们就是创建了一个监听器. ‘参数’ 就是$scope对象下的一个对象

JS中绑定事件顺序(事件冒泡与事件捕获区别)

在JS中,绑定的事件默认的执行时间是在冒泡阶段执行,而非在捕获阶段(重要),这也是为什么当父类和子类都绑定了某个事件,会先调用子类绑定的事件,后调用父类的事件.直接看下面实例 <!Doctype html> <html> <head> <meta charset="utf-8"> <title></title> <style type="text/css"> *{margin:0;p

.Net中的早期绑定和后期绑定(二)

上篇介绍了.Net中绑定的故事背景,在文章的末尾引出了"早期绑定和后期绑定",那么本文就针对.Net中的绑定做一个简单的介绍. 早期绑定 早期绑定:如果在编译时 .Net 能够知道属性或方法所属的对象,就可以预先查找该成员在类型库中的 DispID 或 vtable 地址.这样就无须在运行时调用 GetIDsOfNames.当显式声明了变量的类时,例如 As Class,该变量就只能存放该类的对象的引用..Net 就可以为该变量调用的所有属性和方法使用早期绑定. 后期绑定 在.Net中

.Net中的早期绑定和后期绑定(一)

"绑定"一词在生活是非常常见,像手机绑定.邮箱绑定等等.在.Net中也存在着"绑定",比如说类型的绑定.在进行机房重构的过程中遇到一个特别有意思的现象:B层调用工厂层和接口使其与D层解耦,因此在B层类中的方法都写了这样的语句,以UserBLL类为例: Public Function Login(enUser As Entity.UserEntity) As DataTable '实例化工厂类CreateUser Dim createuser As New Facto

前期绑定、后期绑定

  前期绑定:在程序运行前进行绑定,有编译器和连接程序实现,又叫静态绑定.比如static 方法和final方法,注意这里也包括private方法,因为它也是隐式final的. (在编译时能确定的类型) 后期绑定:在运行时根据对象的类型进行绑定,由方法调用机制实现,因此又叫做动态绑定,或者运行时绑定.除了前期绑定外的所有方法都属于后期绑定. (在运行时才能确定的类型)