复习ECMAScript 5.0第三天

154 阅读7分钟

这是我参与更文挑战的第9天,活动详情查看:更文挑战

with

with是一个语法。 在代码执行的时候,会改变作用域

with (target) {
 	console.log(a) // 如果target中存在a 属性, 那么会优先输出a, 如果没有回沿着词法作用域一直往上查		找
}

举例:

正常模式下:

// 定义对象
var obj = {
	a: 1,
	b: 2
}

var a = 10;
var b = 20;

// 使用with
with (obj) {
	// 此时obj 中 存在a 和 b 那么会优先输出 obj中的a和b 
	console.log(a);
	console.log(b);
	// 此时obj中存在a属性, 所以优先改变的是Obj中的a 
	a = 111;
	// obj中没有c 所以会将c添加在全局中
	c = 123;
}

结果:

图片1.png

严格模式下:

// 开启严格模式
"use strict"
// 定义对象
var obj = {
	a: 1,
	b: 2
}

var a = 10;
var b = 20;
// 使用with
with (obj) {
	// 此时obj 中 存在a 和 b 那么会优先输出 obj中的a和b 
	console.log(a);
	console.log(b);
	// 此时obj中存在a属性, 所以优先改变的是Obj中的a 
	a = 111;
	// obj中没有c 所以会将c添加在全局中
	c = 123;
}

结果:

图片2.png

变量名称

在正常模式下,在一个对象中定义属性可是用名的

严格模式下,不会报错, 只是浏览器检测不出来

正常模式下:

// 定义对象
var obj = {
	a: 1,
	a: 2
}

console.log(obj.a);

输出:

图片3.png

严格模式下:

// 开启严格模式
"use strict"
// 定义对象
var obj = {
	a: 1,
	a: 2
}

console.log(obj.a);

输出:

图片4.png

注:没有区别, 不是严格模式没有开启, 只是浏览器没有实现

全局函数作用域

在全局函数作用域的this指向window, 会污染全局作用域

在严格模式下全局函数作用域中的this 变为undefined, 就可以避免对全局作用域的污染

在正常模式下:

// 定义函数
function fun() {
	var b = 10;
	console.log(b);
	// 全局函数作用域
	console.log(this);
	// 添加属性
	this.color = "red";
}

fun();

结果:

图片5.png

严格模式下:

// 开启严格模式
"use strict"

// 定义函数
function fun() {
	var b = 10;
	console.log(b);
	// 全局函数作用域
	console.log(this);
	// 添加属性
	this.color = "red";
}

fun();

结果:

图片6.png

函数参数

正常模式下,定义函数的参数可以是同名的, 但是后面会覆盖前面的

严格模式下不允许定义同名参数

正常模式下:

// 定义函数
function fun(color, color) {
	console.log(color);
}

fun("red", "blue");

输出:

图片7.png

严格模式下:

// 开启严格模式
"use strict"

// 定义函数
function fun(color, color) {
	console.log(color);
}

fun("red", "blue");

结果:

图片8.png

对象的拓展

特性

对象是什么,我们用属性来描述

属性是什么, 我们用特性来描述

特性是用来描述属性的

Object.defineProperty

作用: 用于设置单个属性的特性

使用方式:

Object.defineProperty(obj, property, options)

obj: 要设置的对象

property: 设置的属性

options: 描述特性对象

举例:

在没有设置特性之前:

// Es5
	var obj = {
		color: "red",
		width: 100
	}

	//使用for循环
	for (var i in obj) {
		console.log(i);
	}

结果:

图片9.png

在设置了特性之后:

// Es5
var obj = {
	color: "red",
	width: 100
}

// 定义特性
Object.defineProperty(obj, "color", {
	// 修改可枚举性
	enumerable: false
})


//使用for循环
for (var i in obj) {
	console.log(i);
}

结果:

图片10.png

特性--配置值

使用方式:

Object.defineProperty(obj, property, {
value:“”
})

举例:

// ES5 
var obj = {
	color: "red"
}

// 定义特性
Object.defineProperty(obj, "color", {
	// 配置值
	value: "green"
})

console.log(obj);

注:如果一个对象中,存在该属性,此时描述特性对象中的其他属性默认都是true

如果一个对象中,没有属性而是通过定义特性的方式添加的属性,那么描述特性对象中的其他属性默认全部是false

特性--可修改性

使用方式:

Object.defineProperty(obj, property, {
writable: false  // 将可修改性设为false
})

举例:

// ES5 
var obj = {
	color: "red"
}

// 定义特性
Object.defineProperty(obj, "color", {
	// 不可写入
	// writable: false
	writable: true
})

// 尝试修改obj.color
obj.color = "blue";
console.log(obj);

设置特性之后将不可修改:

图片11.png

特性--可枚举性

使用方式:

Object.defineProperty(obj, property, {
enumerable: false  // 将可枚举性改为false
})

举例:

// ES5 
var obj = {
	color: "red",
	width: 200
}

// 默认情况下可以被枚举的
// for (var i in obj) {
// 	console.log(i, obj[i]);
// }

// 定义特性
Object.defineProperty(obj, "color", {
	// 修改可枚举性
	enumerable: false
	// enumerable: true
})

// 再次使用for循环
for (var i in obj) {
	console.log(i, obj[i]);
}

结果:

图片12.png

特性--可配置性

使用方式:

Object.defineProperty(obj, property, {
configurable: false  // 将可配置性改为false
})

举例:

// ES5 
var obj = {
	color: "red",
	width: 200
}

// 定义特性
Object.defineProperty(obj, "color", {
	value: "blue",
	// 不可写入
	writable: false,
	// 不可配置
	configurable: false
})

// 再次配置
Object.defineProperty(obj, "color", {
	value: "pink",
	// 不可写入
	writable: true,
})
	
// 尝试修改obj.color
obj.color = "green";
console.log(obj);

修改可配置性为false之后:

图片13.png

特性方法

get用来获取属性值的

没有参数

返回值就是要获取的属性值

作用域是当前对象

千万不要在该方法中获取属性值,否则会递归死循环

通常我们获取该属性的一个备用值

set用来设置值的

参数就是要设置的值

没有返回值

作用域是当前对象

千万不要在该方法中,设置属性值

通常我们设置该属性的一个备用属性

举例:

// 定义对象
var obj = {
	color: "red"
}

// 设置特性
// 一旦设置了特性方法(set, get),当obj.color; 就会触发get函数, 当obj.color = xx; 就会触发set函数
Object.defineProperty(obj, "color", {
	// 取值器
	get: function() {
		console.log(111, this, arguments);
		// 千万不要在方法中获取该属性
		// return this.color;
		// 获取该属性的备用值
		return this._color;
	},
	// 赋值器
	set: function(value) {
		console.log(222, this, arguments);
		// 千万不要设置该属性值
		// this.color = value;
		// 设置该属性的备用值
		this._color = value;
	}
})

obj.color = "blue";
console.log(obj.color);

设置多个属性特性

使用方式: Object.defineProperties(obj, options)

obj: 要设置的对象

options: 特性对象

key: 特性属性

value: 属性特性对象

设置特性属性和方法

举例:

// 定义color和num的特性
Object.defineProperties(obj, {
	color: {
		// 值
		value: "blue",
		// 不可写入
		writable: false,
		// 不可枚举
		enumerable: false
	},
	num: {
		// 取值器
		get: function() {
			return this._num;
		},
		set: function(value) {
			this._num = value;
		},
		// 不可枚举
		enumerable: false,
		// 一旦设置了特性方法(set, get), 将无法再次配置writable, value
		// 不可写入
		// writable: false,
		// 配置值
		// value: 300
	}
})

原型方法

ES5为原型拓展了几个方法

isPrototypeOf

原型对象的方法

用于判断原型对象是否是参数对象的原型

参数就是实例化对象

在查找的时候,会查找整个原型链

// 获取所有div
var obj = document.getElementsByTagName("div");
// 定义数组
var arr = [];

// 数组的原型是哪个对象的原型呢?
console.log(Array.prototype.isPrototypeOf(obj));
console.log(Array.prototype.isPrototypeOf(arr));
// 在查找原型的时候,会查找整个原型链
console.log(Object.prototype.isPrototypeOf(obj));
console.log(Object.prototype.isPrototypeOf(arr));

getPrototypeOf

是对象的静态方法

用于获取原型对象

在ES5之前,获取原型对象的方式,__proto__来获取原型对象, 以__开头,在ES5中不推荐使用, 所以提供了getPrototypeOf方法

// 获取arr的原型对象
console.log(arr.__proto__);
console.log(Object.getPrototypeOf(arr));
console.log(arr.__proto__ === Object.getPrototypeOf(arr));

输出:

图片14.png

setPrototypeOf

作用: 设置某一对象的原型对象(可以是一个对象也可以是null)

使用方式:

Object.setPrototypeOf(obj, prototype)

obj: 将被设置原型的对象

prototype: 新的原型对象 (可以是一个对象也可以是null)

举例:

// 设置arr新的原型对象
// 会修改整个原型链
// Object.setPrototypeOf(arr, null);
Object.setPrototypeOf(arr, {"name": "laowang"});
console.log(Object.getPrototypeOf(arr));

对象的拓展

Object.preventExtensions

作用: 用于取消对象的可拓展性

举例:

// 定义对象
var obj = {
	a: 1
}
// 对象默认是可以拓展了
obj.b = 2;

// 取消对象的可拓展性
Object.preventExtensions(obj);

// 尝试添加属性
obj.c = 3;
console.log(obj); 
// 结果,添加失败, 原因就是取消了对象的可拓展性

总结: 当取消了对象的可拓展性, 仍然可以修改属性值, 删除属性 查看对象是否取消可拓展性: Object.isExtensible(obj) 返回 true | false

// 查看对象的可拓展性是否被取消
console.log(Object.isExtensible(obj));

Object.seal

作用: 用于封闭对象

举例:

// 定义对象
var obj = {
	a: 1
}

// 封闭对象
Object.seal(obj);

总结: 封闭之后 对象可以被访问, 不能拓展, 不能删除属性, 可以修改属性值

查看对象是否被封闭: Object.isSelead(obj) 返回 true | false

Object.freeze

作用: 冻结对象

举例:

// 定义对象
var obj = {
	a: 1
}

// 冻结对象
Object.freeze(obj);

// 添加属性
obj.b = 2;
// 修改属性值
obj.a = 111;
// 删除属性
delete obj.a

console.log(obj);

输出:

图片2.png

总结: 当对象冻结以后: 不能添加属性, 不能修改属性值, 不能删除属性 查看对象是否冻结: Object.isFrozen(obj) 返回 true | false

对象创建的新方式

使用方式: Object.create(prorotype, options)

接受两个参数:

第一个参数是一个对象(可以设置为null)

该对象是Object.create创建出来的原型对象

第二个参数是一个对象(可省略)

该对象是Object.create创建出来的特性对象

举例:

// 创建原型对象
var prototype = {
	say: function() {
		console.log("say");
	},
	sayHello: function() {
		console.log("sayHello");
	},
	sayNihao: function() {
		console.log("sayNihao");
	}
}

// 特性对象
var options = {
	color: {
		// 值
		value: "red",
		// 不可写入
		writable: false
	},
	num: {
		// 值
		value: 200,
		// 不可枚举
		enumerable: false
	}
}

var obj = Object.create(prototype, options);

输出:

图片3.png