JavaScript 学习笔记 之 THIS (二) - 绑定规则

绑定规则

this的绑定规则有四种 

  1. 默认绑定 (全局对象或者undefined(严格模式下))
  2. 隐式绑定(调用时函数上下文对象,obj.fun())
  3. 显式绑定(call , apply , bind(硬绑定))
  4. new绑定(新建的对象会被绑定到构造函数中的this上)

详细介绍

1 . 默认绑定

调用没有任何修饰函数时引用默认绑定,this指向全局对象

但是如果定义时使用严格模式(use strict),则不能将全局对象用于默认绑定,因此this会绑定到undefined,而在严格模式下调用却不影响

2.隐式绑定

调用位置的上下文对象决定,调用函数中的this会指向最后一层调用对象

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}
		obj.foo();//obj

但是隐式绑定存在着一个隐患(隐式丢失)

		var name = "global";
		var bar = obj.foo;
		bar();//global

虽然bar是obj.foo的一个引用,但是实际上引用的是foo函数本身,此时bar()实际上是变成foo(),应用了默认绑定

另一种隐式丢失的情况出现在参数传递中

		function doFoo(fn) {
			fn();
		}

		doFoo(obj.foo) //global

因为参数传递时也会发生隐式赋值 fn = obj.foo

3.显式绑定

function.call(...)

function.apply(...)

这两个函数区别在于第二部分的参数,具体可以看我之前的博客,现在先不讨论这个问题

这两个函数的作用都是将第一个参数绑定到function中的this上,如果第一个参数是个原始值(String Boolean 或者Number),这个原始值会转换成对象形式(new String(..)等),这通常被称为装箱

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}
		
		foo.call(obj);//obj

然而显式绑定依然存在着我们之前提出的丢失绑定的问题

但是显式绑定的的一个变种可以解决这个问题(硬绑定)

		function foo() {
			console.log(this.name);
		}
		var obj = {
			name: "obj",
			foo: foo
		}

		var bar = function() {
			foo.call(obj);
		}
		bar(); //obj

这种方式其实就是ES5中的bind()方法

bind方法与call方法的参数形式是一样的,不同之处在于bind只是返回一个硬绑定了this对象的函数,而call则是绑定了函数中的this对象后执行函数(即使调用call函数的函数本身返回自己,this绑定的对象依然会丢失)

4.new绑定

最后一条this的绑定规则与构造函数有关

JavaScript中的构造函数实际上只是一个使用了new操作符的普通函数

JavaScript实际上不存在所谓的"构造函数",存在的只有对函数的"构造调用"

当函数在new表达式中被调用时,它会初始化新创建的对象

发生的步骤如下

  1. 创建(构造)一个全新的对象
  2. 这个新对象会被执行[[Prototype]]连接(不是本篇讨论的问题,暂时可以忽略)
  3. 这个新对象会被绑定到函数调用的this.

  4. 如果函数没有返回其他对象,则new表达式会自动返回这个新对象
		function foo(a) {
			this.a = a;
		}

		var bar = new foo(2);
		console.log(bar.a);//2

猜你喜欢

转载自blog.csdn.net/Aproducer/article/details/82595384