文章目录
前言
学习地址:https://www.bilibili.com/video/BV1v7411G7Ht?p=1
一、严格模式
ES的几个重要版本
● ES5 : 09年发布。
● ES6(ES2015):2015年发布,也称为ECMA2015。
● ES7(ES2016): 2016年发布,也称为ECMA2016(变化不大)。
1、严格模式的理解
概念
理解∶除了正常运行模式(混杂模式),ES5添加了第二种运行模式:“严格模式” ( strict mode )。
顾名思义,这种模式使得Javascript在更严格的语法条件下运行。
目的:
● 消除Javascript语法的一些不合理、不严谨之处,减少一些怪异行为
● 消除代码运行的一些本安全之处,为代码的安全运行保驾护航
● 为未来新版本的Javascript做好铺垫
使用
● 针对整个脚本文件:将"use stric"
t放在脚本文件的第一行,则整个脚本文件将以严格模式运行。
● 针对单个函数︰将"use strict"
放在函数体的第一行,则整个函数以严格模式运行。
PS:如果浏览器不支持,则这句话只解析为一条简单的语句,没有任何副作用。
脚本文件的变通写法∶因为第一种调用方法不利于文件合并,所以更好的做法是,借用第二种方法,将整个脚本文件放在一个立即执行的匿名函数之中。
语法和行为改变
● 必须用var声明变量
● 禁止自定义的函数中的this指向window
● 创建eval作用域
● 对象不能有重名的属性
2、严格模式和普通模式的区别
全局变量显式声明
在正常模式中,如果一个变量没有声明就赋值,默认是全局变量。严格模式禁止这种用法,全局变量必须显式声明。
禁止this关键字指向全局对象∶
var foo = function (){
console.log(this);
}
foo();
上方代码中,普通模式打印的是window。严格模式下打印的是undefined。
禁止使用with语句
因为with语句无法在编译时就确定,属性到底归属哪个对象。
构造函数必须通过new实例化对象
构造函数必须通过new实例化对象,否则报错。因为this为undefined,此时无法设置属性。
比如说:
var Cat = function(name){
this.name = name;
}
Cat('haha');
上方代码中,如果在严格模式下,则会报错。
属性相关
普通模式下,如果对象有多个重名属性,最后赋值的那个属性会覆盖前面的值。严格模式下,这属于语法错误。
普通模式下,如果函数有多个重名的参数,可以用arguments[i]读取。严格模式下,多个重名的参数属于语法错误。
比如下面这样的代码∶
var obj = {
username : 'smyh' ;
username : 'vae'
}
上面的代码,在严格模式下属于语法错误,因为有重名的属性。
函数必须声明在顶层
将来Javascript的新版本会引入"块级作用域"。
为了与新版本接轨,严格模式只允许在全局作用域或函数作用域的顶层声明函数。也就是说,不允许在非函数的代码块内声明函数。
新增关键字
为了向将来Javascript的新版本过渡,严格模式新增了一些保留字:implements, interface, let, package, private,protected, public, static, yield。
二、对象的扩展
1、JSON对象
1、js对象(数组)–> json对象(数组):
JSON. stringify(obj/arr)
2、json对象(数组)–>js对象(数组)∶
JSON.parse(json)
上面这两个方法是ES5中提供的。
我们要记住,我们通常说的“json字符串”,只有两种: json对象、json数组。
typeof json字符串的返回结果是string。
2、object的扩展
ES5给Object扩展了一些静态方法,常用的有2个,我们接下来讲解。
方法一
object.create(prototype,[descriptors])
作用:以指定对象为原型,创建新的对象。同时,第二个参数可以为为新的对象添加新的属性,并对此属性进行描述。
举例1:(没有第二个参数时)
var a = {
username:"admin",
password:"123456"
}
var b = Object.create(a)
console.log(a)
console.log(b)
打印结果:
a成为了b的原型。
举例2:(有第二个参数时)
第二个参数可以给新的对象添加新的属性。我们修改上面的代码
//传入第二个参数,可设置新对象的属性
var c = Object.create(a,{
mobile:{ //添加新的mobile属性。注意,这一行的冒号不要漏掉
value : '110',//通过value关键字设置mobile的属性值
writable : false, //是否可以修改value值
configurable:true,//是否可以删除掉
enumerable:true
}
})
console.log(c);
打印结果:
上方代码中,我们通过第2行的mobile给c设置了一个新的属性mobile
,但是要通过value
来设置属性值(第3行)。
设置完属性值后,这个属性值默认是不可修改的,要通过writable
来设置。总而言之,这几个关键字的解释如
下:
● value
:设置属性值。
● writable
:标识当前属性值是否可修改。如果不写的话,默认为false,不可修改。
● configurable
:标识当前属性是否可以被删除。默认为false,不可删除。
● enumerable
:标识当前属性是否能用for in枚举。默认为false,不可。
单独设置属性
var mintor = Object.defineProperty(mintor,"type",{
value:"副班长",
writable:true,
configurable:true,
enumerable:true
})
console.log(mintor)
方法二
object.defineProperties(object,descriptors)
作用︰为指定对象定义扩展多个属性。
代码举例:
var obj2 = {
firstName : 'smyh',
lastName : 'vae'
};
object.defineProperties(obj2,{
fullName : {
//获取属性时候调用的函数
get:function () {
return this.firstName + '-'+ this.lastName
},
set:function (data){ //监听扩展属性,当扩展属性发生变化的时候自动调用,自动调用后将变化的值作为实参注入到set函数
var names = data.split('-');
this.firstName = names[0];
this.lastName = names [1];
}
}
});
console.log(obj2.fullName);
obj2.firstName ='tim';
obj2.lastName ='duncan';
console.log(obj2.fullName);
obj2.fullName ='kobe-bryant';
console.log(obj2.fullName);
● get:用来获取当前属性值的回调函数
● set:修改当前属性值得触发的回调函数,并且实参即为修改后的值
存取器属性:setter,getter—个用来存值,一个用来取值。
3、Objec的扩展(二)
obj对象本身就自带了两个方法。格式如下:
get属性名(){}用来得到当前属性值的回调函数
set属性名(){}用来监视当前属性值变化的回调函数
var obj={
firstName:'kobe',
lastName:'bryant',
get fullName(){
return this. firstName +' ' + this. lastName
},
set fullName (data){
var names = data.split(' ');
this.firstName = names [0];
this.lastName = names [1];
}
};
console.log(obj. fullName);
obj. fu11Name = ' curry stephen';
console.log(obj. fullName) ;
4、数组的扩展
方法1:
Array.prototype.indexof(value)
作用︰获取value在数组中的第一个下标。
方法2∶
Array.prototype.lastIndexof(value)
作用:获取value在数组中的最后一个下标。
方法3∶遍历数组
Array.prototype.forEach(function(item,index){})
方法4:
Array.prototype.map(function(item,index){})
作用:遍历数组返回一个新的数组,返回的是加工之后的新数组。
方法5:
Array.prototype.filter(function(item,index){})
作用:遍历过滤出一个新的子数组,返回条件为true的值。
5、函数function的扩展:bind()
ES5中新增了bind()函数来改变this的指向。
Function.prototype.bind(obj)
作用︰将函数内的this绑定为obj,并将函数返回。
面试题: call()、apply()和bind()的区别:
● 都能改变this的指向
● call()/apply()是立即调用函数
● bind():绑定完this后,不会立即调用当前函数,而是将函数返回,因此后面还需要再加()才能调用。
PS : bind()传参的方式和call()—样。
分析:
为什么ES5中要加入bind()方法来改变this的指向呢?因为bind()不会立即调用当前函数。
bind()通常使用在回调函数中,因为回调函数并不会立即调用。如果你希望在回调函数中改变this,不妨使用bind()。