目录
在开始之前我们先来了解一下什么是严格模式。
1. 什么是严格模式
-
JavaScript 除了提供正常模式外,还提供了严格模式(strict mode)。
-
ES5 的严格模式是采用具有限制性 JavaScript变体的一种方式,即在严格的条件下运行 JS 代码。
-
严格模式在 IE10 以上版本的浏览器中才会被支持,旧版本浏览器中会被忽略。
-
严格模式对正常的 JavaScript 语义做了一些更改:
1、消除了 Javascript 语法的一些不合理、不严谨之处,减少了一些怪异行为。
2、消除代码运行的一些不安全之处,保证代码运行的安全。
3、提高编译器效率,增加运行速度。
4、禁用了在 ECMAScript 的未来版本中可能会定义的一些语法,为未来新版本的 Javascript 做好铺垫。比如一些保留字如:class,enum,export, extends, import, super 不能做变量名。
1.1 开启严格模式
严格模式可以应用到整个脚本或个别函数中,可以将严格模式分为为脚本开启严格模式
和为函数开启严格模式
两种情况。
情况一 :为脚本开启严格模式
有的 script 脚本是严格模式,有的 script 脚本是正常模式,这样不利于文件合 并,所以可以将整个脚本文件放在一个立即执行的匿名函数之中。这样独立创建一个作用域而不影响其他 script 脚本文件。
(function (){
//在当前的这个自调用函数中有开启严格模式,当前函数之外还是普通模式
"use strict";
let arr = []
})();
//或者
<script>
"use strict"; //当前script标签开启了严格模式
</script>
<script>
//当前script标签未开启严格模式
</script>
情况二: 为函数开启严格模式
要给某个函数开启严格模式,需要把“use strict”; (或 ‘use strict’; ) 声明放在函数体所有语句之前。
function fn(){
"use strict";
}
//当前fn函数开启了严格模式
注:不管哪种情况下,"use strict"都必须写在第一行才能开启严格模式
this 是 JavaScript 最具“魅惑”的知识点,不同的应用场合 this
的取值可能会有意想不到的结果,在此我们对以往学习过的关于【 this 默认的取值】情况进行归纳和总结。
2、 全局环境下的this指向
在全局作用域下,this始终指向全局对象
window
,无论是否为严格模式
!
那么了解完什么是严格模式后,我们就开始this指向之旅吧。
console.log(this);//window
congsole.log()
完整的写法是window.console.log()
,我们默认会将它省略,window
调用了console.log()
方法,所以此时this指向window。
3、普通函数的this指向
普通函数的调用方式决定了
this
的值,即【谁调用 this 的值指向谁】
不过普通函数内的this分为两种情况,严格模式
下和非严格模式
下。
3.1 严格模式下:
function fn() {
'use strict'
console.log(this);
}
fn()
window.fn()
//函数表达式
const fn1 = function f() {
console.log(this);
}
fn1()
直接fn( )调用函数,this指向undefined
。
window.fn()调用函数this指向window
。因此,在严格模式下, 我们对代码的的调用必须严格的写出是谁调用了这个函数,不可以有省略或者说简写。
注: 在函数表达式中,this也是指向undefined,
并且不能采用window.fn1(),因为window里面没有这个函数。
3.2 非严格模式下:
function fn() {
console.log(this);
}
fn()
在函数表达式中,this也是指向window
const fn1 = function f() {
console.log(this);
}
fn1()
4、 对象中的this指向
对象内部方法的this指向调用这些方法的对象,也就是谁调用就指向谁。
const obj = {
name: '张三',
age: 18,
walk: function () {
console.log(this.name);
}
}
obj.walk()//张三
调用obj.walkl()
方法,返回值为张三
,说明此时this指向obj
。
5、箭头函数中的this
箭头函数中的 this 与普通函数完全不同,也不受调用方式的影响,事实上箭头函数中并不存在 this !
1、箭头函数会默认帮我们绑定外层 this 的值,所以在箭头函数中 this 的值和外层的 this 是一样的
2、箭头函数中的this引用的就是最近作用域中的this
3、向外层作用域中,一层一层查找this,直到有this的定义
<div>11</div>
<script>
document.querySelector('div').addEventListener('click',function() {
console.log(this);
})
document.querySelector('div').addEventListener('click',()=> {
console.log(this);
})
</script>
我们定义一个div标签,给他注册点击事件,使用普通函数的方法,所以则指向div
,
在普通函数里面谁调用就指向谁
。
箭头函数里面没有this,所以向外层作用域中,一层一层查找this,直到有this的定义。最外层是window,所以指向的是window。
5、 构造函数中的this指向
构造函数中的this是指向实例。
function Fn(name,age) {
this.name = name
this.age = age
}
const fn = new Fn('张三',18)
console.log(fn.name);
console.log(fn.age);
由上图可以看出,构造函数中的this指向构造函数下创建的实例。
严格模式下,如果构造函数不加new调用, this 指向的是undefined
如果给他赋值则会报错。
7、改变this指向的方法
有时候,我们需要改变this的值,这时就可以使用call( )、apply( )、或bind( )等方法。
7.1 call()和apply()方法
call()和apply()方法可以用来改变函数中this的值,并立即调用
该函数。
两者的区别在于传参方式的不同,call()方法传参以逗号
相隔,apply()方式传参以数组
的形式。
我们来看段小例子理解一下:
const obj = {
name: '张三'
}
function fn(x, y) {
console.log(this, x, y);
}
fn(1, 2)
fn.call(obj, 1, 2)//call方法
fn.apply(obj, [1, 2])//apply方法
默认情况下fn()中的this是指向window,通过call()和apply()方法将this指向对象obj。
7.2 bind()方法
bind()方法可以用来改变函数中this的值,并返回一个原拷贝函数,也就是一个新的函数,不同于 call()和apply()方法,它不会立即调用该函数,所以在很多时候用的最多的就是bind()方法。
const obj = {
name: '张三'
}
function fn(x, y) {
console.log(this, x, y);
}
fn(1, 2)
const binds = fn.bind(obj, 1, 2)
binds()