整体介绍
认识对象
1)认识对象
2)对象的方法
3)对象的遍历
4)对象的深浅克隆
认识函数的上下文
1)上下文规则1
2)上下文规则2
3)上下文规则3
4)上下文规则4
4)上下文规则5
5)上下文规则6
7)call和apply
构造函数
1)用new调用函数的四步走
2)构造函数
3)类和实例
原型和原型链
1)prototype和原型链查找
2)在prototype上添加方法
3)原型链的终点
4)继承
上升到面向对象
1)上升到面向对象小案例1
2)上升到面向对象小案例2
JS的内置对象
1)包装类
2)Math对象
3)Date对象
认识对象
对象(object)是”键值对”的集合,表示属性和值的映射关系
对象的语法
k和V之间用冒号分隔,每组k:V之间用逗号分隔,最后一个k:v对后可以不书写逗号
属性是否加引号
如果对象的属性键名不符合JS标识符命名规范,则这个键名必须用引号包裹
属性的访问
可以用“点语法”访问对象中指定键的值
如果属性名不符合]S标识符命名规范,则必须用方括号的写法来访问
如果属性名以变量形式存储,则必须使用方括号形式
属性的更改
直接使用赋值运算符重新对某属性赋值即可更改属性
属性的创建
如果对象本身没有某个属性值,则用点语法赋值时,这个属性会被创建出来
属性的删除
如果要删除某个对象的属性,需要使用delete操作符
对象的方法
如果某个属性值是函数,则它也被称为对象的“方法”
方法的调用
◆使用“点语法”可以调用对象的方法
xiaoming.sayHello();
方法和函数
方法也是函数,只不过方法是对象的“函数属性”,它需要用对象打点调用
对象的遍历
和遍历数组类似,对象也可以被遍历,遍历对象需要使用for…in…循环
使用for…in…循环可以遍历对象的每个键
for…in..循环
对象的深浅克隆
对象是引用类型值
对象是引用类型值,这意味着:
不能用var obj2=obj1这样的语法克隆一个对象,把obj2指向与obj1同样的堆内存区域
使用或者=进行对象的比较时,比较的是它们是否为内存中的同一个对象,而不是比较值是否相同
在例子三中,obj4不会克隆obj3这个对象,而是指向obj3,obj3.a++,obj4也会跟着改变,所以obj3和obj4压根是同一个对象
对象的浅克隆
复习什么是浅克隆:只克隆对象的“表层”,如果对象的某些属性值又是引用类型值,则不进一步克隆它们,只是传递它们的引用
使用for…in..循环即可实现对象的浅克隆
对象里有数组,数组是引用类型值,需要使用递归将c这个数组里的克隆出来,而for循环无能为力,所以叫浅克隆
对象的深克隆
复习什么是深克隆:克隆对象的全貌,不论对象的属性值是否又是引用类型值,都能将它们实现克隆
和数组的深克隆类似,对象的深克隆需要使用递归
面试时经常会考察深克隆算法,必须掌握
认识上下文
函数上下文
函数中可以使用this关键字,它表示函数的上下文
与中文中“这”类似,函数中的this具体指代什么必须通过调用函数时的“前言后语”来判断
函数的上下文由调用方式决定
函数的上下文(this关键字)由调用函数的方式决定,function是”运行时上下文”策略
◆函数如果不调用,则不能确定函数的上下文
同一个函数,用不同的形式调用它,则函数的上下文不同
情形1:对象打点调用函数,函数中的this指代这个打点的对象
xiaoming.sayHello();
情形2:圆括号直接调用函数,函数中的this指代window对象
var sayHello = xiaoming.sayHello;
sayHello();
this不知道,函数只有被调用。它的上下文才能被确定
如果只有obj.fn();
,答案就为3,如果是var fn = obj.fn; fn()
,答案就为NaN
此时答案为13,因为此处this指代window对象,windows对象是全局变量,即定义的var a和var b
上下文规则1
规则1:对象打点调用它的方法函数,则函数的上下文是这个打点的对象
对象.方法()
上下文规则2
规则2:圆括号直接调用函数,则函数的上下文是window对象
函数()
上下文规则3
规则3:数组(类数组对象)枚举出函数进行调用,上下文是这个数组(类数组对象)
数组[下标]()
类数组对象
什么是类数组对象:所有键名为自然数序列(从开始),且有length,属性的对象
◆arguments对象是最常见的类数组对象,它是函数的实参列表
上下文规则4
◆规则4:IIFE中的函数,上下文是window对象
(function(){})();
上下文规则5
规则5:定时器、延时器调用函数,上下文是window对象
setInterval(函数,时间);
setTimeout(函数,时间);
上下文规则6
规则6:事件处理函数的上下文是绑定事件的DOM元素
DOM元素.onclick=function(){}
call和apply
call和apply能指定函数的上下文
函数.call(上下文);
函数.apply(上下文);
cal和applyl的区别
到底使用call还是apply?
arguments是伪数组
但就是77
上下文规则总结
用new调用函数的四步走
用new操作符调用函数
现在,我们学习一种新的函数调用方式:
new 函数()
你可能知道new操作符和“面向对象”息息相关,但是现在,我们先不探讨它的”面向对象”意义,而是先把用new调用函数的执行步骤和它上下文弄清楚
JS规定,使用new操作符调用函数会进行”四步走”:
1)函数体内会自动创建出一个空白对象
2)函数的上下文(this)会指向这个对象
3)函数体内的语句会执行
4)函数会自动返回上下文对象,即使函数没有return语句
四步走详解
第1步:函数体内会自动创建出一个空白对象
第2步:函数的上下文(this)会指向这个对象
第3步:执行函数体中的语句
第4步:函数会自动返回上下文对象,即使函数没有return语句
上下文规则继续总结:
构造函数
什么是构造函数
我们将之前书写的函数进行一下小改进:
用new调用一个函数,这个函数就被称为“构造函数”,任何函数都可以是构造函数,只需要用new调用它
顾名思义,构造函数用来“构造新对象”,它内部的语句将为新对象添加若干属性和方法,完成对象的初始化
构造函数必须用new关键字调用,否则不能正常工作,正因如此,开发者约定构造函数命名时首字母要大写
构造函数名称首字母约定大写
构造函数中的this不是函数本身
此处的this是新对象,将来会成为xiaoming,xiaohong,xiaogang
尝试为对象添加方法
类与实例
类好比是“蓝图”
如同“蓝图”一样,类只描述对象会拥有哪些属性和方法,但是并不具体指明属性的值
构造函数和“类”
Java、C++等是”面向对象”(object-oriented)语言
JavaScript是“基于对象”(object-based)语言
JavaScript中的构造函数可以类比于OO语言中的”类”
写法的确类似,但和真正OO语言还是有本质不同,在后续课程还将看见JS和其他00语言完全不同的、特有的原型特性
JS使用构造函数充当类
prototype和原型链查找
什么是prototype
任何函数都有prototype属性,prototype是英语”原型”的意思
prototype,属性值是个对象,它默认拥有constructor属性指回函数
普通函数来说的prototype属性没有任何用处,而构造函数的prototype,属性非常有用构造函数的prototype属性是它的实例的原型
原型链查找
◆JavaScript规定:实例可以打点访问它的原型的属性和方法,这被称为“原型链查找”
原型的遮蔽效应: 小明这个实例找不到国籍这个属性,就会在原型上去找,如果能在自身找到,就不会去寻找原型上的属性
hasOwnProperty
hasOwnProperty方法可以检查对象是否真正”自己拥有’某属性或者方法
in
in运算符只能检查某个属性或方法是否可以被对象访问,不能检查是否是自己的属性或方法
在prototype上添加方法
把方法直接添加到实例身上的缺点:每个实例和每个实例的方法函数都是内存中不同的函数,造成了内存的浪费
◆解决办法:将方法写到prototype.上
方法要写到prototype上
原型链的终点
关于数组的原型链
继承
继承描述了两个类之间的”is a kind of”关系,比如学生“是一种”人,所以人类和学生类之间就构成继承关系
◆People是”父类”(或”超类”、“基类”);Student是“子类”(或“派生类”)
◆子类丰富了父类,让类描述得更具体、更细化
JavaScript中如何实现继承
实现继承的关键在于:子类必须拥有父类的全部属性和方法,同时子类还应该能定义自己特有的属性和方法
◆使用JavaScript特有的原型链特性来实现继承,是普遍的做法
在今后学习ES6时,将介绍新的实现继承的方法
通过原型链实现继承
包装类
Number()、String()和Boolean()分别是数字、字符串、布尔值的“包装类”
很多编程语言都有“包装类”的设计,包装类的目的就是为了让基本类型值可以从它们的构造函数的prototype上获得方法
包装类知识总结
Number()、String()和Boolean()的实例都是object类型,它们的PrimitiveValue属性存储它们的本身值
new出来的基本类型值可以正常参与运算
包装类的目的就是为了让基本类型值可以从它们的构造函数的prototype上获得方法
Math(数学)对象
已经学习过的Math对象的方法
◆幂和开方:Math.pow()、Math.sqrt()
◆向上取整和向下取整:Math.ceil()、Math.floor()
四舍五入Math.round()
Math.round()可以将一个数字四舍五入为整数
四舍五入到小数点后某位
如何才能实现“四舍五入到小数点后某位”呢?
Math.max()和Math.min()
◆Math.max()可以得到参数列表的最大值
◆Math.min()可以得到参数列表的最小值
console.log(Math.max(6,2,9,4)); //9
console.log(Math.min(6,2,9,4)); //2
如何利用Math.max()求数组最大值
Math.max()要求参数必须是“罗列出来”,而不能是数组
还记得apply方法么?它可以指定函数的上下文,并且以数组的形式传入“零散值”当做函数的参数
随机数Math.random()
◆Math.random()可以得到0~1之间的小数
◆为了得到[a,b]区间内的整数,可以使用这个公式:
parseInt(Math.random()*(b-a +1))+a
Date(日期)对象
◆使用new Date()即可得到当前时间的日期对象,它是object类型值
◆使用new Date(2020,11,1)即可得到指定日期的日期对象,注意第二个参数表示月份,从0开始算,11表示12月
◆也可以是new Date(‘2020-12-01’)这样的写法
日期对象的常见的方法
时间戳
◆时间戳表示1970年1月1日零点整距离某时刻的毫秒数
◆通过getTime()方法或者Date.parse()函数可以将日期对象变
为时间戳
◆通过new Date(时间戳)的写法,可以将时间戳变为日期对象