`

javascript的动态this与动态绑定

阅读更多
javascript是一门动态语言,最明显就是那个dynamic this。它一般都是作为函数调用者存在。在javascript,所有关系都可以作为对象的一个关联数组元素而存在。那么函数就是被掰成两部分储存于对象,一是其函数名(键),一是函数体(值),那么函数中的this一般都指向函数所在的对象。但这是一般而已,在全局调用函数时,我们并没有看到调用者,或者这时就是window。不过,函数声明后,其实并没有绑定到任何对象,因此我们可以用call apply这些方法设置调用者。
一个简单的例子:
window.name = "window";
var run = function() {
  alert("My name is " + this.name);
}
run();

运行代码
这里你不能说run是作为window的一个属性而存在,但它的确是被window属性调用了。实质上大多数暴露在最上层的东西都则window接管了。在它们需要调用时被拷贝到window这个对象上(不过在IE中window并不继承对象),于是有了window['xxx']与window.xxx性能上的差异。这是内部实现,不深究了。
另一个例子,绑定到一个明确的对象上
window.name = "window";
object = {
  name: "object",
  run: function() {
    alert("My name is " + this.name);
  }
};
object.run();

运行代码
答案显然易见,this总是为它的调用者。但如果复杂一点呢?
window.name = "window";
object = {
   name: "object",
   run: function() {
     var inner = function(){
       alert("My name is " + this.name);
     }
     inner();
   }
};
object.run();

运行代码
尽管它是定义在object内部,尽管它是定义run函数内部,但它弹出的既不是object也不是run,因为它既不是object的属性也不是run的属性。它松散在存在于run的作用域用,不能被前两者调用,就只有被window拯救。window等原生对象浸透于在所有脚本的内部,无孔不入,只要哪里需要到它做贡献的地方,它都义不容辞。但通常我们不需要它来帮倒忙,这就需要奠出call与apply两大利器了。
window.name = "window";
var object = {
  name: "object",
  run: function() {
    inner = function() {
     alert( this.name);
    }
    inner.call(this);
  }
}

object.run();

运行代码
call与apply的区别在于第一个参数以后的参数的形式,call是一个个,aplly则都放到一个数组上,在参数不明确的情况,我们可以借助arguments与Array.slice轻松搞定。
window.name = "Window";

var cat = {
  name: "Cat"
};
var dog = {
  name: "Dog",
  sound: function(word) {
    alert(this.name + word);
  }
};

dog.sound(" is pooping");
dog.sound.call(window, " is banking");
dog.sound.call(dog, " is banking");
dog.sound.apply(cat, [" miaowing"]);

运行代码
由此Prototype开发者搞了一个非常有名的函数出来,bind!以下是它的一个最简单的版本:
var bind = function(context, fn) {
  return function() {
    return fn.apply(context, arguments);
  }
}

运行代码
不过为了面对更复杂的情况建议用以下版本。
function bind(context,fn) {
  var args = Array.prototype.slice.call(arguments, 2);
  return args.length == 0 ? function() {
    return fn.apply(context, arguments);
  } : function() {
    return fn.apply(context, args.concat.apply(args, arguments));
  };
};
它还有一个孪生兄弟叫bindAsEventListener ,绑定事件对象,没什么好说的。
var bindAsEventListener = function(context, fn) {
    return function(e) {
        return fn.call(context, (e|| window.event));
    }
}
Prototype的版本
Function.prototype.bind = function() {
   if (arguments.length < 2 && (typeof arguments[0]==='undefined'))
     return this;
   var _slice = Array.prototype.slice
   var __method = this, args = _slice.call(arguments,0), context = args.shift();
   return function() {
     return __method.apply(context, args.concat(_slice.call(arguments,0)));
   }
}

运行代码
bind函数是如此有用,google早早已把它加入到Function的原型中了(此外还有inherits,mixin与partial)。

运行代码
有绑定就有反绑定,或者叫剥离更好!例如原生对象的泛化方法我们是无法通过遍历取出它们的。
for(var i in Array){
  alert(i + " : "+ Array[i])
}
for(var i in Array.prototype){
  alert(i + " : "+ Array.prototype[i])
}

运行代码
要取出它们就需要这个东西:
var _slice = Array.prototype.slice;
function unbind(fn) {//第一步取得泛化方法
  return function(context) {//第二部用对应原生对象去重新调用!
    return fn.apply(context, _slice.call(arguments, 1));
  };
};
示例以前也给过了,请见这里
总结:
this 的值取决于 function 被调用的方式,一共有四种,
如果一个 function 是一个对象的属性,该 funtion 被调用的时候,this 的值是这个对象。如果 function 调用的表达式包含句点(.)或是 [],this 的值是句点(.)或是 [] 之前的对象。如myObj.func 和myObj["func"] 中,func 被调用时的 this 是myObj。
如果一个 function 不是作为一个对象的属性,那么该 function 被调用的时候,this 的值是全局对象。当一个 function 中包含内部 function 的时候,如果不理解 this 的正确含义,很容易造成错误。这是由于内部 function 的 this 值与它外部的 function 的 this 值是不一样的。解决办法是将外部 function 的 this 值保存在一个变量中,在内部 function 中使用它来查找变量。
如果在一个 function 之前使用 new 的话,会创建一个新的对象,该 funtion 也会被调用,而 this 的值是新创建的那个对象。如function User(name) {this.name = name}; var user1 = new User("Alex"); 中,通过调用new User("Alex") ,会创建一个新的对象,以user1 来引用,User 这个 function 也会被调用,会在user1 这个对象中设置名为name 的属性,其值是Alex 。
可以通过 function 的 apply 和 call 方法来指定它被调用的时候的 this 的值。 apply 和 call 的第一个参数都是要指定的 this 的值。由于它们存在,我们得以创建各种有用的函数。
分享到:
评论

相关推荐

    详细讲解JavaScript中的this绑定

    `this`在JavaScript中并不像其他语言中的`this`那样简单地指向对象本身,而是根据函数调用的方式动态确定其指向。理解`this`的工作方式对于编写高质量的JavaScript代码至关重要。 1. **默认绑定**: - 当函数被...

    JavaScript高级-this绑定规则+箭头函数

    JavaScript中的`this`绑定规则是理解JavaScript面向对象编程的关键概念之一。`this`关键字在不同情况下会有不同的指向,主要取决于函数的调用方式。这里我们将深入探讨四种主要的`this`绑定规则:默认绑定、隐式绑定...

    复习JavaScript中this指向及绑定

    复习JavaScript中this指向及绑定

    javascript下动态this与动态绑定实例代码

    本文将探讨JavaScript中动态this的特性以及如何动态地绑定this,包括使用call、apply方法,以及bind方法的实现。 首先,JavaScript中的函数可以作为一等公民存在,这意味着函数可以赋值给变量,作为参数传递,也...

    【JavaScript源代码】vue 中this.$set 动态绑定数据的案例讲解.docx

    案例中的代码展示了如何使用 `this.$set` 绑定不同类型的动态数据: 1. **单个数据绑定**: 在 `&lt;template&gt;` 中,有一个按钮点击事件 `text0a`。当按钮被点击时,`text0a` 方法会被调用,通过 `vm.$set` 设置 `...

    Javascript的this详解

    在JavaScript中,`this`的绑定遵循四个主要规则:默认绑定、隐式绑定、显式绑定和new绑定。让我们逐一深入理解这些规则。 1. **默认绑定**:在非严格模式下,如果函数没有明确的上下文,`this`会绑定到全局对象,这...

    Javascript中this绑定的3种方法与比较

    JavaScript中的`this`关键字是一个非常重要的概念,它在不同的上下文环境中会有不同的...记住,`this`的值是在函数调用时确定的,而不是定义时,这是JavaScript中的一大特性,也是它与其他静态类型语言的一个重要区别。

    跟我学习javascript的this关键字

    `this`关键字是动态绑定的,也称为运行期绑定,这意味着它会根据函数调用的方式和所在的上下文来改变其指向。这种动态绑定的特性给JavaScript带来了灵活性,但同时也可能导致一些困惑,特别是对于初学者。 在...

    Javascript中神奇的this

    JavaScript中的`this`关键字是一个非常重要的概念,它与许多其他编程语言中的行为不同,因此常常让开发者感到困惑。本文将详细解析`this`在JavaScript中的工作原理及其绑定规则。 1. `this`并不总是指向函数自身 ...

    reactnative 绑定this1

    这是因为JavaScript中的this上下文是根据函数调用方式动态决定的,而不是像其他语言那样在定义时固定。这可能导致在某些场景下,如事件处理函数中,this指向了非预期的对象,例如不是我们期望的组件实例。 在ES5中...

    Javascript的this用法

    这也就意味着`this`的值可以在运行时动态改变。 #### `this`的不同行为 ##### 1. 全局上下文中`this`的行为 当我们在全局作用域(即非任何函数内部)使用`this`时,它指向全局对象(在浏览器环境中是`window`对象...

    JavaScript程序设计javascript中this

    `bind`返回一个新的函数,其`this`值被绑定到指定的对象,即使在其他上下文中调用新函数,`this`依然保持不变。 ```javascript let obj1 = {name: "Tom"}; let obj2 = {name: "Jerry"}; function logName() { ...

    Javascript 中 this指向

    Javascript 中 this 指向 在Javascript中,this 指向是一个非常重要的概念,它的指向规律影响着函数的执行结果。理解 this 的指向是开发任务的必备技能。 首先,我们需要区分清楚作用域链和this是两套不同的系统,...

    JavaScript中this指向.pdf

    如果没有指定参数,call和apply默认将this绑定到全局对象window。例如,可以使用apply方法调用一个函数,并指定该函数的this值为某个特定对象。 5. 原生Function方法bind的调用 bind方法可以创建一个新的函数,新...

    JavaScript动态网站开发案例指导

    - 箭头函数:理解其与传统函数的区别,如this指向和作用域。 - async/await:学习异步编程的新方式,简化Promise链式调用。 6. **Web存储与API交互** - Web Storage:了解localStorage和sessionStorage,用于在...

    简单谈谈javascript中this的隐式绑定

    总的来说,理解JavaScript中的`this`隐式绑定需要深入探究调用栈和调用位置。正确理解`this`的工作原理对于编写高效和无误的JavaScript代码至关重要。在实际开发中,要时刻留意`this`可能的绑定情况,避免出现预期...

    将JavaScript事件绑定到ASP.NET对象

    在ASP.NET框架中,JavaScript事件绑定是将客户端脚本与服务器端控件相结合,以实现动态交互和优化用户体验的关键技术。尽管ASP.NET提供了丰富的服务器端功能,但JavaScript在处理页面上的实时交互和验证等方面具有...

    详解Javascript 中的this指针

    `this`的值并不是静态绑定的,而是取决于函数调用的方式,这一点与许多静态类型的语言如C++或Java不同,这些语言中的`this`或`self`关键字通常指向实例对象。 #### `this`指针的动态特性 JavaScript中的`this`具有...

Global site tag (gtag.js) - Google Analytics