三:以理论结合实践方式梳理前端 ES 6+ ——— ES 6+ 内置对象

本文详细介绍了JavaScript中的内置对象如Number、String、Array等,以及对象的创建方式、函数声明与调用、匿名闭包回调、内存回收机制、变量作用域和作用域链。同时,讲解了错误处理和异常捕获,帮助理解JavaScript中的核心概念和技术要点。
摘要由CSDN通过智能技术生成

ES 6+ 内置对象

JavaScript 设计中内置了许多对象:Number、String、Boolean、Null、Undefined、Symbol、Object、Array、Date、Math、Function、RegExp、Error对象

对象声明

对象是一种特殊的引用数据类型,拥有属性和方法,JavaScript 中所有的事务都是对象:字符串、数值、数组、函数等

  • 使用对象实例化方式创建对象:var obj = new Object();
  • 使用对象字面量方式创建对象:var obj = {};
function say() {
	console.log('miao');
}
var obj = new Object();
obj.name = 'Tom';
obj.age  = 5;
obj.say = say;					// 需要通过 obj.say() 方法调用
obj.say = say();				// 需要通过 obj.say 方法调用

var obj = {
	name: 'Tom',
	age: 5,
	say: function() {			// 匿名函数
		console.log('miao');
	}
};

通过使用函数来构造对象,就可以通过创建对象实例

function person(name, sex, age) {
	this.name = name;
	this.sex = sex;
	this.age = age;
}
var tom = new person('Tom', 'boy', 12);
console.log(tom.name, tom.sex, tom.age);
var lily = new person('Lily', 'girl', 10);
console.log(lily.name, lily.sex, lily.age);

函数声明

函数是定义一次但却可以调用或执行任意多次的一段 JS 代码,函数有时会有参数,通过调用函数进行参数的传递,有些函数也会将函数体执行的结果返回出来,这个返回值也是函数调用表达式的值。

语法:function fun-name([args]) { 函数执行体; }

有、无参数函数

function message() {					// 经常使用采用这种模式声明
	console.log('hello world');
}
message();								// 函数本身是不执行的,只有被调用时才执行
var message = function() {				// 执行体系大,采用这种模式声明
	console.log('hello world');
}

function myAdd(a, b) {
	console.log('两个数的和为:' + (a + b));
}
myAdd(2, 3);							// 5

返回数据

函数通过 return 返回函数体执行的结果,在函数调用时返回,并赋值给一个变量,return 发生了执行,后续代码无意义,不执行

function message() {
	return 'hello world';
}
var msg = message();					// msg = 'hello world'

function myAdd(a, b) {
	return a + b;
}
var sum = myAdd(2, 3);					// sum = 5

形参实参

  • 形参:就是函数在声明定义的时候参数变量
  • 实参:就是函数在调用传值的时候传递数据

JavaScript 中函数的形参设置多少,实参个数可以与形参个数不同,是被允许的,arguments 为函数的形参对象,是一个伪数组

arguments 有一个指针函数 callee(),用于指向 arguments 所在的函数,参考下面:# 内部指针

function addNum() {
	for(var sum = 0, i = 0; i < arguments.length; i++) {
		sum += arguments[i];
	}
	return sum;
}
var sum = addNum(2,5, 5);			// sum = 12
var sum = addNum(12, 4);			// sum = 16

匿名闭包回调

  • 匿名函数:就是没有名字的函数,单独的匿名函数是没法自身运行和调用的,常用于赋值,也可通过表达式运行
  • 闭包函数:就是函数内返回的一个可访问当前函数作用域的内部函数体,驻留局部变量,避免使用全局变量
  • 回调函数:通过一个函数调用另外一个函数,回调函数通常作为一个函数的参数传递,等到这个函数执行完成之前,调用回调函数
function addNum(a, b) {}			// 普通函数
var addNum = function(a, b) {};		// 等号右侧就是一个匿名函数,通过 addNum()
(function(a, b) {})(a, b);			// 表达式调用匿名函数,JQuery 的封装就是一个表达式的匿名函数
// 把匿名函数执行结果赋值给变量,与上面不同,上面是把匿名函数赋值给变量,变量就成了 Function 引用类型
var addNum = (function(a, b) { return a + b; })(a, b);
--------------------------------------------------------------------------------------------------------------------------------
for (var i = 0; i < 5; i++) {
	setTimeout(function() { console.log(i); }, i * 1000 );
}
解析:上面的代码不会按预期显示值01234,而是会显示 55555,原因是:在循环中执行的每个函数将整个循环完成之后被执行,会导致计时器函数引用存储的最有一个 i = 5 的值,所以会输出:55555
for (var i = 0; i < 5; i++) {
    (function(x) {
        setTimeout(function() { console.log(x); }, x * 1000 );
    })(i);
}
--------------------------------------------------------------------------------------------------------------------------------
function cat(name, callback) {
	callback(name + 'see Jerry');
}
cat('Tom', function(message) { console.log(message); });			// "Tom see Jerry"

内存回收

在 JavaScript 定义的全局变量是不会被立即回收的,只有当关闭浏览器时,才会触发回收机制,垃圾不回收容易导致运行卡顿、内存溢出等现象,对于内存管理,是开发者必备的一块技术点,如何优化 JavaScript 的内存管理:

  • 善用函数,普通函数的创建,有时候会导致变量的提升,从而内存不会立即释放,推荐使用匿名函数方式
  • 使用普通函数,需要手动解除变量引用,重置为 null,从而减少内存占用,释放内存
  • 绝对不要定义全局变量,通过匿名函数传值发方式传递局部变量,也可以通过回调函数方式进行变量传值
for(var i = 0; i < 5; i++) {}
console.log(i);						// 5 不会被销毁
// 使用块模块封装,处理全局变量内存管理
(function() {
	for(var i = 0; i < 5; i++) {}
})();
console.log(i);						// Uncaught ReferenceError: i is not defined
--------------------------------------------------------------------------------------------------------------------------------
;(function(document, window){
	var btns = document.querySelectorAll('.btn');
	var output = document.querySelector('#output');
	var arrs = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
	for(var i = 0; i < btns.length; i++) {
		btns[i].onclick = (function(num){
			return function() {
				output.innerText += 'Clicked ' + num;
			};
		})(arrs[i]);
	}
})(document, window);

内部指针

  • arguments.callee() 返回正被执行的 Function 对象,常用于匿名函数的递归或者保证函数的封装性
  • this 默认指向 window(JavaScript 里面最大的对象,最外围的对象),可以指向当前对象或引用对象
  • apply() 用于设置 this 的指向,默认 this 指向 window,参数是那个对象,调用方法中的 this 就指向这个对象
function factorial(num) {									// 数的阶乘计算
	if (num <= 1) { return 1; } 
	return num * arguments.callee(num - 1);					// 会存在一个调用记录,每次调用就会形成一个调用栈
}
var res = factorial(3);										// !3 = 3 * 2 * 1 = 6
PS:不推荐使用 arguents.callee(),访问 arguments 是个很昂贵的操作,它是个很大的对象,每次递归调用时都需要重新创建,影响现代浏览器的性能,还会影响闭包,解决方法就是给内部函数指定一个名字,在条件满足是,尾调用这个函数
function factorial(num) {									// 数的阶乘计算
	return (function tailFactorial(num, total) {
		if(num === 1) return total;
		return tailFactorial(n - 1, n * total);				// 尾调用自己
	})(num, 1);
}
var res = factorial(3);										// !3 = 3 * 2 * 1 = 6
--------------------------------------------------------------------------------------------------------------------------------
function currying(fn) {
	return function(list) {
		return fn.call(this, list);							// 使用柯里化
	}
}
function recursion(list) {
	return (function tailRecursion(item, arr) {
		arr.push(item + 1);
		if(list.length === 0) return arr;
		return tailRecursion(list.splice(0,1)[0], arr)
	})(list.splice(0,1)[0], [])
}
var res = currying(recursion)([1, 2, 3, 4, 5]);				// res = [2, 3, 4, 5, 6]
--------------------------------------------------------------------------------------------------------------------------------
function recursion(list, arr = []) {						// ES 6 语法
	var item = list.splice(0,1)[0];
	arr.push(item + 1);
	if (list.length === 0) {
		return arr;
	}
	return recursion(list, arr);
}
var res = recursion([1, 2, 3, 4, 5]);
var color = 'red';
var car = {
	name: '大众',
	color: this.color							// this 指向 window:是 JavaScript 里面最大的对象,最外围的对象
};
--------------------------------------------------------------------------------------------------------------------------------
var car = {
	name: '大众',
	text: 'green',
	color: function() {
		return this.text;						// this 指向 car
	}
};
car.color();
--------------------------------------------------------------------------------------------------------------------------------
function person() {
	this.name = 'zhangsan';						// this 指向引用对象 person()
}
var zs = new person();
zs.name;										// 'zhangsan'
--------------------------------------------------------------------------------------------------------------------------------
function say() {
	console.log(this.text);						// this 指向引用对象 cat
}
var cat = {};
cat.text = 'miao';
cat.say = say;
cat.say();										// 'miao'
var person = {
	fullName: function() {
		return this.fName + ' ' + this.lName;	// 这里的 this 就对应到 apply 传入的对象
	}
};
var zs = {
	fName: 'zhang',
	lName: 'san'
};
person.fullName.apply(zs);						// zhang san
--------------------------------------------------------------------------------------------------------------------------------
function addNum1(a, b) {
	console.log(this);
	return a + b;
}
function addNum2(a, b) {
	return addNum1.apply(this, [a, b]);			// this 指向 window,apply 用于调用自身方法
}
addNum2(2, 3);
--------------------------------------------------------------------------------------------------------------------------------
function addNum1(a, b) {
	console.log(this);
	return a + b;
}
function addNum2(a, b) {
	return addNum1.call(this, a, b);			// this 指向 window,apply 用于调用自身方法
}
addNum2(2, 3);

变量作用域

JavaScript 内所有的函数的参数都是局部变量,没有引用传递方式

function message(text) {
	text = '改变';
}
var text = '原来';
message(text);									// text = '原来'
--------------------------------------------------------------------------------------------------------------------------------
function message(obj) {
	obj.name = 'Tom';
}
var obj = new Object();
message(obj);									// obj.name = 'Tom'
--------------------------------------------------------------------------------------------------------------------------------
function message(obj) {
	obj.name = 'Tom';
	var obj = new Object();
	obj.name = 'Jerry';							// 由于重新声明了一个引用类型,地址不同
}
var obj = new Object();
message(obj);									// obj.name = 'Tom'
  • 全局变量:在外环境中,在任何地方都可以读取使用到的变量,所有的全局变量都是在 window 下
  • 局部变量:在内代码块,仅在内部才能访问使用的变量,函数参数也是局部作用
function message() {
	return 'this is message';
}
var msg = 'hello world';
console.log(window.message());					// this is message
console.log(window.msg);						// hello world
--------------------------------------------------------------------------------------------------------------------------------
function message() {
	var msg = 'hello world';
	return 'this is message';
}
console.log(window.message());					// this is message
console.log(window.msg);						// undefined
--------------------------------------------------------------------------------------------------------------------------------
function message() {
	msg = 'hello world';
	return 'this is message';
}
console.log(window.message());					// this is message
console.log(window.msg);						// hello world (不推荐,全局变量最好写最外面)

作用域链

作用域链核心思想:变量的作用域始终是从里往外走,函数定义会预解析,变量不会

var name = 'tom';
function f() {
	name = 'jerry';
}
f();											// name = 'jerry';
--------------------------------------------------------------------------------------------------------------------------------
var name = 'tom';
f();											// name = 'jerry';
function f() {
	name = 'jerry';
}
--------------------------------------------------------------------------------------------------------------------------------
function f1() {
	var name = 'tom';
	function f2() {
		var name = 'jerry';
		function f3() {
			var name = 'terry';
			console.log(name);					// name = 'terry'
		}
		f3();
	}
	f2();
}	
--------------------------------------------------------------------------------------------------------------------------------
message();										// 预解析:“miao”
function message() {
	console.log('miao');
}	
--------------------------------------------------------------------------------------------------------------------------------
console.log(a);									// undefined
var a = 10;
--------------------------------------------------------------------------------------------------------------------------------
var name = 'tom';
function show() {
	console.log(name);
	var name = 'jerry';
}
show();											// undefined
--------------------------------------------------------------------------------------------------------------------------------
console.log(show);								// ƒ show() { console.log('function'); }
function show() {
	console.log('function');
}
var show = 'var_value';
console.log(show);								// 'var_value'
--------------------------------------------------------------------------------------------------------------------------------
var name = 'tom';
show();
function show() {
	console.log(name);							// undefined
	var name = 'jerry';
}
--------------------------------------------------------------------------------------------------------------------------------
var tom = 'tom';
show();
function show() {
	var jerry = 'jerry';
	console.log(tom);							// undefined
	console.log(jerry);							// 'jerry'
	var tom = 'cat';
}
--------------------------------------------------------------------------------------------------------------------------------
show();
console.log(cat);								// 会报错
console.log(mouse);								// 'like'
console.log(dog);								// 'like'
function show() {
	var cat = mouse = dog = 'like';				// mouse 和 dog 没有使用 var 是全局变量
	console.log(cat);							// 'like'
    console.log(mouse);							// 'like'
    console.log(dog);							// 'like'
}

异常处理

  • try :测试代码块的错误
  • catch:处理错误
  • throw:创建自定义错误
  • finally:测试代码块后执行,不管有无异常
function message() {
	try {
		adddlert("Welcome guest!");
	} catch(err) {
		console.log(err);
	}
}
message();										// ReferenceError: adddlert is not defined
--------------------------------------------------------------------------------------------------------------------------------
function myFunction(val) {
	try {
		if(val == '') throw 'empty';
		if(isNaN(val)) throw 'not a number';
		if(val > 10) throw 'too high';
		if(val < 5) throw 'too low';
	} catch(err) {
		console.log(err);
	}
}
myFunction(NaN);								// not a number
myFunction('');									// empty
--------------------------------------------------------------------------------------------------------------------------------
function myClear() {
	try {
		throw new Error('出错了...');
	} finally {
		console.log('清理完成');
	}
}
myClear();										// 清理完成
错误属性属性描述
name设置或返回一个错误名
message设置或返回一个错误信息(字符串)
function say() {
	try {
		add(2, 3);
	} catch(err) {
		console.log(err.name);						// ReferenceError
		console.log(err.message);					// ReferenceError
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值