严格模式
在js代码最前面使用’use strict’
启用严格模式。
1.变量必须用var定义
下面这种形式没有使用var关键字定义,严格模式下,该文件会报错。
// 会报错
'use strict';
username = 'zhangsan';
console.log(username); // 打印username的值
严格模式下必须使用var关键字定义变量:
// 不会报错
'use strict';
var username = 'zhangsan';
console.log(username);
2.改变eval变量的作用域
没有使用严格,eval()函数中定义的变量将是全局的
var str = 'var a = 10; alert(a)';
eval(str);
// 这里可以使用eval()中定义的a变量
console.log(a)
如果使用了严格模式,eval()函数中定义的变量仅限于eval()函数中使用。
'use strict';
var str = 'var a = 10; alert(a)';
eval(str);
// 变量a是在eval()函数中定义的,使用了严格模式a变量不能直接使用
console.log(a)
3.禁止自定义函数中的this指向window
非严格模式下,函数中的this是指向window的:
function fun(name, age) {
this.name = name;
this.age = age;
}
fun('zs', 18);
console.log(this.name)
console.log(this.age)
在严格模式下,函数中的this必须是对应的实例对象:
'use strict'
function fun(name, age) {
this.name = name;
this.age = age;
}
// 构造实例对象
var f = new fun('zs', 18);
// 访问实例对象的属性
console.log(f.name)
// 严格模式,this不指向window,所以window中没有age属性
console.log(window.age)
4.严格模式下对象属性不能重名
非严格模式下,下面是没有语法错误的:
var obj = {
username: 'zs',
username: 'lisi'
};
但是在严格模式下,是有语法错误的!
JSON对象
1.json概念
JSON:JavaScript 对象表示法(JavaScript Object Notation)。JSON本质是一个字符串,但是JSON对象字符串是以{开头}结束,JSON数组对象是以[开头,]结束。JSON对象的属性值的表示方式是键值对我方式,键和值都是用""引起来。
例如JSON对象:
{"username":"zs","age":18}
JSON数组:
["a","b","c"]
JSON对象数组:
[{"username":"zs","age":18},{"username":"zs","age":18},{"username":"zs","age":18}]
2.JSON对象与js对象的相互转换:
js对象转换成JSON对象:
var o = {
username: 'zs',
age: 18
};
JSON.stringify(o)
JSON对象转换成js对象
var o0 = {
username: 'zs',
age: 18
};
var o1 = {
username: 'zs',
age: 18
};
var o2 = {
username: 'zs',
age: 18
};
// 把对象封闭成数组
var arr = [o0, o1, o2]
// 把数组转换成json对象
var json = JSON.stringify(arr);
// 把json转换成对象
var obj = JSON.parse(json);
Object对象扩展
1.Object.create(prototype, descriptions)
var obj = {
username: 'zs',
password: '12345'
}
// obj作用原型,在原型的基础上扩展
var newObj = Object.create(obj, {
age: {
value: 18, // 指定这个对象的值
writable: true, // 指定扩展的这个属性是否能被修改,false的话这个属性是不能修改民的
configurable: true, // 指定扩展的这个属性是否能被删除,false的话这人属性是不能被删除的
enumerable: true // 指定扩展的这个属性是否能被for in枚举出来
},
address: {
value: '中国',
writable: false, // 默认值都是false
configurable: false,
enumerable: false
}
})
console.log("扩展对象是", newObj);
for (ele in newObj) {
console.log(ele) // address的enumerable的值是false是false,所以不能枚举出这个属性的
}
newObj.age = 20;
newObj.address = "深圳"; // 这个对象的扩展属性address的wirtable是 false,所以是不能修改属性的值的
console.log(newObj)
delete newObj.age;
delete newObj.address; // address属性的configurable是false,所以这个属性不能删除的
console.log(newObj);
2.Object.defineProperties(object, description)
var obj = {
username: 'zs',
password: '12345'
}
// 这对象obj的基础上添加一个info属性,这个属性是惰性的,只有在使用的时候才会计算这个属性的值
var obj1 = Object.defineProperties(obj, {
info : {
get() {
return "对象的username属性是:" + this.username + ", 密码是:" + this.password;
},
set(data) {
console.log(data); // 这里的data就是obj1.info = "haha";设置的值haha,但是要自己通过get的方式去修改info的值
}
}
});
obj1.info = "haha";
console.log(obj1)
3.普通对象的get和set方法
var obj = {
username: 'zs',
password: '12345',
// 添加了一个info属性,这个属性也是惰性的
get info() {
return "这是info属性"
},
set info(data) {
console.log("为info属性设置值", data)
}
}
obj.info = "hhh"
console.log(obj.info);
console.log(obj)
数组的操作
1.indexof(value)获取value在数组中第一次出现的下标
var arr = [1, 3, 5, 7, 9, 7, 5, 3, 1];
// 获取3在数组arr第一次出现的下标,这里应该是1
var indexof = arr.indexOf(3)
console.log(indexof);
2.lastIndexOf(value)获取value在数组中最后一次出现的下标
var arr = [1, 3, 5, 7, 9, 7, 5, 3, 1];
// 获取3在数组arr最后一次出现的下标,这里应该是7
var lastIndexOf = arr.lastIndexOf(3)
console.log(lastIndexOf);
3.遍历数组中的元素forEach()
var arr = [1, 3, 5, 7, 9, 7, 5, 3, 1];
// 遍历数组arr中元素
arr.forEach(function(item, index) {
console.log(index + " -> ", item);
})
4.构建新的数组map()
var arr = [1, 3, 5, 7, 9, 7, 5, 3, 1];
// 构建新的数组,如果item
var arr1 = arr.map(function(item, index) {
if (item > index) {
return item;
} else {
return index;
}
})
console.log(arr1);
5.数组过滤
// 数组的过滤
var arr2 = arr.filter(function(item, index) {
// 返回数组中值比下标大的数
return item > index;
});
console.log(arr2);
函数的扩展
下面这个函数中的this默认是window对象
function fun(data) {
console.log("data->", data);
console.log("this->", this); // 这里的this是window对象
}
fun("123")
1.call()
使用call()方法可以改变函数中this的指向,如下fun函数中的this就指向了obj对象。
var obj = {username: 'zs', age: 19};
function fun(data1, data2) {
console.log("data1->", data1);
console.log("data2->", data2);
console.log("this->", this); // 这里的this是window对象
}
// 函数会立即执行
fun.call(obj, "12345");
2.apply()
var obj = {username: 'zs', age: 19};
function fun(data1, data2) {
console.log("data1->", data1);
console.log("data2->", data2);
console.log("this->", this); // 这里的this是window对象
}
// apply()方法接收的参数必须是数组形式,函数会立即执行
fun.apply(obj, ["12345", "54321"]);
3.bind()
bind()不同于apply()和call(),函数使用bind,函数不会被立即执行。并且bind()方法会返回一个新的函数。
var obj = {username: 'zs', age: 19};
function fun(data1, data2) {
console.log("data1->", data1);
console.log("data2->", data2);
console.log("this->", this); // 这里的this是window对象
}
var bindFun = fun.bind(obj);
// 这样也能传参
bindFun('1', 2);
bind时传参:
var obj = {username: 'zs', age: 19};
function fun(data1, data2) {
console.log("data1->", data1);
console.log("data2->", data2);
console.log("this->", this); // 这里的this是window对象
}
// 返回一个函数,在这里传了参数
var bindFun = fun.bind(obj, '22', 33);
// 调用这个函数,不用传参。
bindFun();
例如在使用定时器时,回调函数中的this是指向window的,我们可以通过bind()将this指向指定的对象:
var obj = {username: 'zs', age: 18}
// 改变this的指向,使this指向obj这个对象
setTimeout(function() {
console.log(this)
}.bind(obj), 1000);
回调函数
最简的回调函数的理解:
// 定义一个函数,这个函数接收一个函数作为回调函数
function fun(callback) {
if (callback instanceof Function) {
callback();
} else {
throw callback + "不是一个函数";
}
}
// 定义一个函数
function fun1() {
console.log("回调")
}
// 调用接收回调函数的函数
fun(fun1);
// 如果传入的不是函数,抛出了异常
fun(11);