文章目录
首先
- JS中存在变量提升,实际上提升的是声明,而不是初始化
- 不同于Java反射中method.invoke(obj),Java在运行时使用指令invokedynamic动态解析,与静态解析一样会判断obj对应的类是否持有method,否则会报出异常。而JavaScript中一个函数可以被独立执行,也可以绑定到任何对象上执行,这是因为:JS中函数被单独保存在内存中,然后再返回函数的地址,地址可以绑定到任何对象的属性上
严格模式
为了消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为,提高编译效率和运行速度,官方提出了严格模式,通过在代码前声明’use strict’来显式开启,而且它同时支持全局
或局部
。
-
全局
"use strict" myFunction();
-
局部
function myFunction() { "use strict"; y = 3.14; // 报错 (y 未定义) }
严格模式下有诸多限制,对于this指向我们只需要关心这几个特性:
- 非严格模式下,全局对象为node:global、browser:window,严格模式下,全局对象为undefined;
- 严格模式下,不能使用未声明的变量(并不影响变量提升);
- delete 操作不能删除全局变量(包括对象和函数)(是因为全局对象为undefined)
this关键字
JS中的this关键字行为,与其他语言有所不同,且自身在严格模式(use strict)
与非严格模式
下也有差别。
全局上下文(函数外)
- 无论是否为严格模式,均指向全局对象。
注意:严格模式下全局对象为undifined
函数上下文(函数内)
-
默认的,指向函数的调用对象,且是最直接的调用对象:
- 简单调用,指向全局对象
注意:严格模式下全局对象为undifined,某些浏览器未实现此标准也可能会是window
- 简单调用一
var o = { prop: 37, f: function() { return this.prop; } }; var f = o.f; console.log(f()); // 37
- 简单调用二
function func(){ return this; } console.log(func()); // 37
- 简单调用三
var o = { prop: 37, f: function() { return func(); } }; function func(){ return this; } console.log(o.f()); // 37
- 简单调用一
- 作为对象本身属性调用;
- 将函数作为属性传递给新对象,调用;
- 原型链继承函数调用;
- Getter、Setter调用;
- 简单调用,指向全局对象
-
Function.prototype.call(this,...args)
、Function.prototype.apply(this,[arg0,arg1...])
指定调用对象; -
Function.prototype.bind(this,...args)
绑定,bind()方法创建一个新函数,生成的新函数忽略之后所有的bind(),并且this被bind方法的第一个参数永久绑定,之后不管它如何被调用都不会发生改变
; -
箭头函数,没有自己的this绑定,它将会保留封闭词汇上下文中的this值,
在箭头函数创建时被设置
,且之后无论是:- 将函数作为属性传递给新对象,调用、
call
、apply
直接指定调用对象、- 还是
bind
都不会改变this,(注意:
call
,bind
, orapply
,仍然能够传递调用参数,可以把第一个参数设置为null); -
将函数作为构造方法(使用new关键字),this指向正在构造的新对象。注意:默认情况下构造方法返回this,但是可以通过return返回值来修改,不过,如果返回值不是对象(e.g 1,“test”),那么仍将返回this;
-
作为Dom事件处理函数,this指向触发事件的Dom元素对象:
document.querySelector("#id").addEventListener("click",function(){ alert(this); }); //HTTPElement document.querySelector("#id").onclick = function(){ alert(this); }; //HTTPElement
-
作为行内on-event处理函数,this指向所在Dom元素对象,事实上这个
this
与事件对象event
一样,是直接将确定的值,传递到JavaScript脚本中:<button onclick="alert(this.tagName.toLowerCase());"> Show this </button> <button onclick="document.getElementById('demo').innerHTML=this;"> Show this </button>
-
特殊的,当函数在另一个函数中调用的时候,同样遵守上述所有规则。
如下所有情况,最终都是简单调用,指向全局对象,严格模式下全局对象为undefined
。document.querySelector("#id").addEventListener("click",function(){ alert(test()); }); //[object Window] function test(){ return this }
<button onclick="alert(test());"> Show this </button> <button onclick="alert((function() { return this; })());"> Show this </button>