JavaScript学习(第一天)
JavaScript第二天
JavaScript第三天
JavaScript第四天(面向对象,构造函数和原型)高级
JavaScript第五天(函数,this,严格模式,高阶函数,闭包,递归,正则,ES6)高级
预解析、对象、内置对象
1 JavaScript预解析
1.1 预解析
我们js引擎运行js分为两步: 预解析
和代码执行
(1). 预解析js引擎会把js里面所有的var还有function提升到当前作用域的最前面
(2). 代码执行 按照代码书写的顺序从上往下执行
1.2 变量预解析和函数预解析
预解析分为变量预解析(变量提升) 和函数预解析(函数提升)
(1) 变量提升,就是把所有的变量声明
提升到当前的作用域最前面 不提升赋值操作,所有var
(2)函数提升,就是把所有的函数声明
提升到当前作用域的最前面不调用函数
,所有函数
//变量提升
console.log(num);//unfined
var num = 10;
//相当于执行了一下代码,先预解析,剩下的代码依次罗列
var num;
console.log(num);//unfined
num = 10;
//变量提升
funn();//报错
var fun = function() {
console.log(22);
}
//相当于执行了以下代码
var fun;
funn();//报错
fun = function() {
console.log(22);
}
//函数提升
fn();
function fn() {
console.log(11);
}
//相当于执行了以下代码
function fn() {
console.log(11);
}
fn();
1.3 预解析案例
案例一:
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
//相当于执行以下代码
//外部变量var 和函数, 提到当前作用域最前面,剩下的代码按顺序排列
var num;
function fun() {
console.log(num);
var num = 20;
}
num=10;
fun();
//
var num;
function fun() {
var num;
console.log(num);
num = 20;
}
num=10;
fun();
//输出结果是undefined
案例二:
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
//相当于下面这些代码
function f1() {
var a;
a = b = c = 9;
//相当于var a = b = c = 9;b和c直接赋值 没有var 声明 当全局变量看
//集体声明 var a = 9; b = 9; c = 9;
console.log(a);
console.log(b);
console.log(c);
}
f1();
console.log(c);
console.log(b);
console.log(a);
2 JavaScript对象
2.1 对象
2.1.1什么是对象?
现实生活中:万物皆对象,对象是一个具体的事物
,看得见摸得着的实物。例如,.一本书、一辆汽车、 一个人可以是”对象”, 一个数据库、一张网页、 一个与远程服务器的连接也可以是“对象”。
在JS中,对象是一组无序的相关属性和方法的集合
,所有的事物都是对象,例如,字符串,数值,数组,函数等。
对象是由属性
和方法
组成的
- 属性:事物的特征,在对象中用
属性
来表示(常用名词) - 方法:事物的行为,在对象中用
方法
来表示(常用动词)
2.1.2 为什么需要对象
- 保存一个值时,可以使用变量,
- 保存多个值(一组值)时,可以使用数组,
- 保存一个人的完整信息
JS中的对象表达结构更清晰,更强大
2.2 创建对象的三种方式
在JS中,现阶段我们可以采用三种方式创建对象(object):
- 利用
字面量
创建对象 - 利用
new Object
创建对象 - 利用
构造函数
创建对象
2.2.1 利用字面量
创建对象
对象字面量
:就是花括号{}
里面包含了表达这个具体事务(对象)的属性和方法。
1、利用对象字面量创建对象
- 里面的属性或者方法,我们采取键值对的形式,键:值---->属性名:属性值
- 多个属性或方法中间用逗号隔开,最后一个可以不用跟逗号
- 方法冒号后面跟的是一个匿名函数
2、使用对象
- 调用对象的
属性
,我们采取对象名.属性
- 调用对象的
属性
,我们采取对象名['属性名']
- 调用对象的
方法
, 我们采取对象名.方法名()
//1、利用对象字面量创建对象
var obj = {};//创建了一个空的对象
var obj = {
uname: '张三丰',
age:18,
sex:'男',
sayHi: function() {
console.log('hi~');
}
}
//(1)里面的属性或者方法,我们采取键值对的形式,键:值---->属性名:属性值
//(2)多个属性或方法中间用逗号隔开
//2、调用对象的属性
//(1)(不用加引号)对象名.属性
console.log(obj.uname);
//(2)(加引号)对象名['属性名']
console.log(obj['uname']);
//3、调用对象的方法 对象名.方法名() 千万别忘记添加小括号
obj.sayHi();
3、变量、属性、函数、方法总结
-
变量:单独声明赋值,单独存在
-
属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征
-
函数:单独存在的,通过"
函数名()
”的方式就可以调用 -
方法:对象里面的函数称为方法,方法不需要声明,使用“
对象.方法名()
”的方式就可以调用,方法用来描述该对象的行为和功能。
2.2.2 利用new Object
创建对象
和创建数组差不多var arr = new Array();
创建
- var obj = new Object();//创建一个空的对象
- obj.uname = ‘张三丰’;//利用追加的方式添加属性
- 利用等号 = 赋值的方法 添加对象的属性和方法
- 每个属性和方法之间用分号结束
调用
- console.log(obj.uname);//对象名.属性
- console.log(obj[‘uname’]);//对象名[‘属性名’]
- obj.sayHi();//对象名.方法名(),千万别忘记添加小括号
//利用`new Object `创建对象
var obj = new Object();//创建一个空的对象
obj.uname = '张三丰';//利用追加的方式添加属性
obj.age = 18;
obj.sex = '男';
obj.sayHi = function() {
console.log('hi~');
}
}
//(1)利用等号 = 赋值的方法 添加对象的属性和方法
//(2)每个属性和方法之间用分号结束
2.2.3 利用构造函数
创建对象
为什么使用构造函数,:因为前面两种创建对象的方式,一次只能创建一个对象
- 我们可以利用函数的方式,重复这些相同的代码,我们就把这个函数称为
构造函数
- 里面封装的不是代码,而是对象
- 构造函数,就是把我们对象里面一些相同的属性和方法抽象出来,封装到函数里面
function 构造函数名() {
this.属性 = 值;
this.方法 = function () { }
}
1.构造函数名字首字母要大写
2.我们构造函数不需要return,就可以返回结果
3.我们调用构造函数,必须使用new
4.我们只要new Star(),调用函数就创建了一个对象
5.我们的属性和方法前面必须添加this
// 我们需 要创建四大天王的对象相同的属性: 名字年龄性别相同的方法: 唱歌
// new构造函数名();
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', 18, '男');//调用函数返回的一个对象(object),只要new 构造函数名就可以生成对象
console.log(ldh.name);//ldh的名字
console.log(ldh['age']);
ldh.sing('冰雨')
var zxy = new Star('张学友', 19, '男');
console.log(zxy.name);//zxy的名字
console.log(zxy['age']);//zxy的年龄
2.2.4 构造函数和对象
- 构造函数,如Stars(),抽象了对象的公共部分,封装到了函数里面,它泛指某一大类
- 创建对象,如new Stars() ,特指某一个,通过new 关键字创建对象的过程我们称为
对象实例化
2.3 new关键字
new关键 字执行过程
1. new构造函数可以在内存中创建了一个空的对象
2.this就会指向刚才创建的空对象
3.执行构造函数里面的代码给这个空对象添加属性和方法
4.返回这个对象
function Star(uname, age, sex) {
this.name = uname;
this.age = age;
this.sex = sex;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华', 18, '男');
2.4 遍历对象属性
for...in
用于对数组或者对象的属性进行循环操作
for...in
遍历对象
for (变量 in 对象) {
}
<script>
var obj = {
name:'老师',
age: 18,
sex: '男',
}
for (var k in obj) {
console.log(k);//k变量输出,得到的是属性名
console.log(obj[k]);//obj[k] 得到的是属性值
}
//我们使用 for in 里面的变量 我们喜欢写 k 或者 key
</script>
3 JavaScript 内置对象
3.1 内置对象
- JavaScript中的对象分为3种:自定义对象、内置对象、浏览器对象
- 前两种对象是JS基础,属于ECMAScript;
- 第三种浏览器对象属于我们JS独有的,在JS API中说明
内置对象
:就是指JS语言自带的一些对象,这些对象供开发者使用,并提供了一些常用的或者最基本而有必要的功能(属性和方法)- 内置对象最大的优点是:
帮助我们快速开发
- JS提供了多个内置对象:Math、Date、Array、String等。
3.2 查文档
MDN和W3C
学习一个内置对象的使用,只要学会其常用成员的使用即呵, 我们可以通过查文档学习,可以通过MDN、W3C来查询。
Mozilla开发者网络( MDN )提供了有关开放网络技术( Open Web )的信息,包括HTML、CSS和万维网及HTML5 应用的API.
MDN: https://developer.mozilla.org/zh-CN
3.3 Math对象
Math数学对象不是一个构造函数,所以我们不需要new来调用而是直接使用里面的属性和方法即可。
<script>
// Math数学对象不是一个构造函数,所以我们不需要new来调用而是直接使用里面的属性和方法即可
console.log(Math.PI); //一个属性圆周率 3.141592653589793
console.log(Math.max(1, 99, 3)); // 99
console.log(Math.max(-1, -10)); // -1
console.log(Math.max(1, 99, 'pink老师')); // NaN
console.log(Math.max()); // - Infinity
</script>
3.3.1 封装自己的数学对象
<script>
//利用对 象封装自己的数学对象里面有PI最大值和最小值
var myMath = {
PI: 3.141592653,
max: function () {
var max = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] > max) {
max = arguments[i];
}
}
return max;
},
min: function() {
var min = arguments[0];
for (var i = 1; i < arguments.length; i++) {
if (arguments[i] < min) {
min = arguments[i];
}
}
return min;
}
}
console.log(myMath.PI);
console.log(myMath.max(1, 5, 9));
console.log(myMath.min(1, 5., 9));
</script>
3.3.2 Math概述
Math对象不是构造函数,它具有数学常数和函数的属性和方法。跟数学相关的运算(求绝对值,取整、最大值等)可以使用Math中的成员。
Math.PI //圆周率
Math. floor() //向下取整
Math.ceil () //向上取整
Math. round() //四舍五入版就近取整 注意-3.5 结果是-3(.5往大了取)
Math.abs () //绝对值
Math.max() /Math.min() // 求最大和最小值
<script>
//1.绝对值方法
console.log(Math.abs(1));//绝对值就是1
console.log(Math.abs(-1));//绝对值就是1
console.log(Math.abs('-1'));//1,隐式转换,会把字符串型 -1 转换为数字型
console.log(Math.abs('老师'));//NaN
//2.三个取整方法
//(1)Math.floor() 向下取整 ,往最小了取
console.log(Math.floor(1.1));//1
console.log(Math.floor(1.9));//1
//(2)Math.ceil() 向上取整 ,往最大了取
console.log(Math.ceil(1.1));//2
console.log(Math.ceil(1.9));//2
//(3)Math.round() 其他数字都是四舍五入,但是.5例外,它往最大了取
console.log(Math.round(1.1));//1
console.log(Math.round(1.5));//2
console.log(Math.round(1.9));//2
console.log(Math.round(-1.5));//-1
console.log(Math.round(-1.9));//2
</script>
3.3.2 随机数方法 random()
<script>
// 1.Math对 象随机数方法random() 返回一个随机小数 e =< X < 1
//2.这个方法里面不跟参数
console.log(Math.random());
// 4.我们想要得到两个数之间的随机整数并且包含这2个整数
// Math.floor(Math.random() * (max - min + 1)) + min;
function getRandom(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
console.log(getRandom(1, 10));
//5.随机点名
var arr = ['张三', '张三丰','张三疯子','李四','李思思','pink老师'];
//console.log(arr[0]);
console.log(arr[getRandom(0, arr.length-1)]);
</script>
3.4 Date日期对象
3.4.1 Date概述
- Date对象和Math对象不太一样,他是一个构造函数,我们需要实例化后才可以使用
- Date实例用来处理日期和时间
3.4.2 Date()方法的使用
1、获取当前时间必须实例化
var now = new Date();
console.log(now);
<script>
//Date()日期对象是一个构造函数必须使用new来调用创建我们的日期对象
var arr = new Array(); //创建一个数组对象
var obj = new Object(); //创建了一个对象实例
// 1.使用Date如果没有参数返回当前系统的当前时间
var date = new Date();
console.log(date);
// 2.参数常用的写法 数字型 2019, 10, 01 或者是字符串型'2019-10-1 8:8:8'
var date1 = new Date (2019, 10, 1);
console.log(date1);//返回的式11月不是10月
var date2 = new Date ('2019-10-1 8:8:8');
console.log(date2);
</script>
2、Date 构造函数的参数
如果括号里面有时间,就返回参数里面的时间,例如日期格式字符串为’2019-5’(最常用),或者new Date(‘2019/5/1’)
3.4.3 日期格式化
<script>
// 格式化日期 年月日
var date = new Date();
console.log(date.getFullYear()); //返回当前日期的年2019
console.log(date.getMonth() + 1); //月份返回的月份 小1个月 记得月份+1 呦\
console.log(date. getDate()); //返回的是几号
console.log(date.getDay()); // 3周一返回的是 1周六返回的是6但是周日返回的是0
//我们写一个2019年 5月1日星期三
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var arr = ['星期日','星期一','星期二','星期三','星期四','星期五','星期六'];
var day = date.getDay();
console.log('今天是:'+year+'年'+month+'月'+dates+'日' + arr[day]);
</script>
<script>
var date = new Date();
console.log(date.getHours()); //时
console.log(date.getMinutes()); //分
console.log(date.getSeconds()); //秒
//要求封装个函数返回 当前的时分秒格式08:08:08
function getTime() {
var time = new Date();
var h = time.getHours();
h = h < 10 ? '0' + h : h;
var m = time.getMinutes();
m = m < 10 ? '0' + m : m;
var s = time.getSeconds();
s = s < 10 ? '0' + s : s;
return h + ':' + m + ':' + s;
}
console.log(getTime());
</script>
3.4.4 获取日期的总的毫秒(时间戳)
<script>
//获得Date总的毫秒数(时间戳)不 是当前时间的毫秒数 而是距离1970年1月1号过了多少毫秒数
// 1.通过valueOf() getTime()
var date = new Date();
console.log(date.valueOf()); //就是我们现在时间距离1970.1.1总的毫秒数
console.log(date.getTime());
// 2.简单的写法(最常用的写法)
var date1 = +new Date(); // +new Date() 返回的就是总的毫秒数
console.log(date1);
// 3. H5新增的获得总的毫秒数
console.log(Date.now());
</script>
3.5 数组对象
3.5.1 数组对象的创建
两种方式:
- 字面量方式
- new Array()
<script>
//创建数组的两种方式
// 1.利用数组字面量
var arr = [1, 2, 3];
console.log(arr[0]);
// 2.利用new Array( )
//var arr1=newArray();//创建了一个空的数组
// var arr1 = new Array(2);
//这个2表示数组的长度为2里面有2个空 的数组元素
var arr1 = new Array (2, 3); //等价于[2,3] 这样写表示里面有2个数组元素是2和3
console.log(arr1);
</script>
3.5.2检测是否为数组
- arr instanceof Array
- Array. isArray(参数)
// (1) instanceof 运算符它可以用来检测是否为数组
var arr = [];
var obj = {};
console.log(arr instanceof Array);
console.log(obj instanceof Array);
// (2) Array. isArray(参数); H5新增的方法,ie9以上版本支持
console.log(Array.isArray(arr));
console.log(Array.isArray(obj));
3.5.3 添加删除数组元素的方法
添加
//添加删除数组元素方法
// 1. push() 在我们数组的末尾添加一个或者 多个数组元素 push推
var arr = [1, 2, 3];
// arr . push(4, 'pink');
console .log(arr.push(4, 'pink'));
console.log(arr);
// (1) push 是可以给数组追加新的元素
// (2) push() 参数直接写数组元素就可以了
// (3) push完毕之后,返回的结果是新数组的长度
// (4) 原数组也会发生变化
// 2. unshift 在我们数组的开头添加一个或者多个数组元素
console.log(arr .unshift('red', 'purple' ));
console.log(arr);
// (1) unshift 是可以给数组前面追加新的元素
// (2) unshift() 参数直接写数组元素就可以了
// (3) unshift完毕之后,返回的结果是新数组的长度
// (4) 原数组也会发生变化
删除
//3.pop()它可以删除数组的最后一个元素
console .log(arr.pop());
console.log(arr);
// (1) pop是可以删除数组的最后一个元素记住一 次只能删除一 个元素
// (2) pop() 没有参数
// (3) pop完毕之后,返回的结果是删除的那个元素
// (4) 原数组也会发生变化
// 4. shift() 它可以删除数组的第一个元素
console.log(arr.shift());
console.log(arr);
//(1)shift是可以删除数组的第一个元素记住一次只能删除一个元素
// (2) shift() 没有参数
// (3) shift完毕之后,返回的结果是删除的那个元素
// (4) 原数组也会发生变化
3.5.4 数组排序
<script>
// 数组排序
// 1.翻转数组
var arr = ['pink', 'red', 'blue'];
arr.reverse();
console.log(arr);
//2.数组排序(冒泡排序)
var arr1 = [13, 4, 77, 1, 7];
arr1.sort(function (a, b) {
// return a - b;升序的顺序排列
return b - a; //降序的顺序排列
});
console.log(arr1);
</script>
3.5.5 数组索引方法
//返回数组元素索引号方法 indexOf(数组元素) 作用就是返回该数组元素的索引号从前面开始查找
//它只返回第一个满足条件的索引号
// 它如果在该数组里面找不到元素, 则返回的是-1
//var arr=['red',' green', 'blue', 'pink', 'blue'];
var arr = ['red', 'green', 'pink'];
console.log(arr.indexOf('blue'));
//返回数组元素索引号方法lastIndex0f(数组元素) 作用就是返回该数组元素的索引号从后面开始查找
var arr = ['red',' green','blue', 'pink', 'blue'];
console.log(arr .lastIndexOf('blue')); // 4
3.5.6 数组转换为字符串
<script>
//数组转换为字符串
// 1. toString() 将我们的数组转换为字符串
var arr = [1, 2, 3];
console.log(arr.toString()); //1, 2, 3
//2. join(分隔符)
var arr1 = ['green', 'blue', 'pink'];
console.log(arr1.join()); // green, blue, pink
console.log(arr1.join('-')); // green - blue - pink
console.log(arr1.join('&')); // green & blue & pink
</script>
3.6 字符串对象
3.6.1基本包装类型
为了方便操作基本数据类型, JavaScript 还提供了三个特殊的引用类型: String、Number和Boolean.
基本包装类型就是把简单数据类型包装成为复杂数据类型**,这样基本数据类型就有了属性和方法**。
//下面代码有什么问题?
var str = 'andy' ;
console. log (str. length);
按道理基本数据类型是没有属性和方法的,而对象才有属性和方法,但上面代码却可以执行,这是因为js会把基本数据类型包装为复杂数据类型,其执行过程如下:
// 1.生成临时变量,把简单类型包装为复杂数据类型var temp = new String('andy');
// 2.赋值给我们声明的字符变量
str = temp;
// 3.销毁临时变量
temp = null;
3.6.2 字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间
3.6.3根据字符串返回位置
字符串所有的方法,都不会修改字符串本身(字符串是不可变的),操作完成会返回一个新的字符串
str.indexOf(要查找的字符串)
var str = ‘改革春风,春天’
console.log(str.indexOf(‘春’));//根据字符返回位置
str.indexOf('要查找的字符串',[起始的位置])
3.6.4 根据位置返回字符
<script>
//根据位置返回字符
// 1. charAt(index) 根据位置返回字符
var str = 'andy';
console.log(str.charAt(3));
//遍历所有的字符
for (var i = 0; i < str.length; i++) {
console.log(str.charAt(i));
}
// 2. charCodeAt(index) 返回相应索引号的字符ASCII值目的: 判断用户按下了那个键
console.log(str.charCodeAt(0)); // 97
// 3. str[index] H5新增的
console.log(str[0]); // a
</script>
一个对象是否有该属性 对象[‘属性名’]
3.6.5 字符串操作方法
//字符串操作方法
// 1. concat(字符串1',字符串2....)
var str = 'andy';
console.log(str.concat('red'));
// 2. substr( ' 截取的起始位置', '截取几个字符');
var str1 = '改革春风吹满地';
console.log(str1.substr(2, 2)); //第一个2是索引号的2从第几个开始第 二个2是取几个字符
// 1.替换字符replace('被替换的字符','替换为的字符) 它只会替换第一个字符
var str = ' andyandy';
console.log(str.replace('a', 'b'));
//有一个字符串' abcoefoxyozzopp' 要求把里面所有的o,替换为*
var str1 = 'abcoefoxyozzopp ';
while (str1.indexOf('o') !== -1) {
str1 = str1.replace('o', '*');
}
console.log(str1);
// 2.字符转换为数组splif('分隔符')
//前面我们学过join把数组转换为字符串
var str2 = 'red, pink, blue';
console.log(str2.split(','));
var str3 = 'red&pink&blue';
console.log(str3.split('&'));
toUpperCase();//转化为大写
toLowerCase();//转换为小写
4 JavaScript 简单数据类型和复杂数据类型
4.1 简单类型与复杂类型
简单类型又叫做基本数据类型或者值类型,复杂类型又叫做引用类型。
- 值类型: 简单数据类型/基本数据类型,在存储时变量中存储的是值本身,因此叫做值类型 string , number,boolean ,undefined,null
- 引用类型: 复杂数据类型,在存储时变量中存储的仅仅是地址(引用) ,因此叫做引用数据类型,通过new关键字创建的对象(系统对象、自定义对象) , 如Object, Array, Date等
4.2 堆和栈
堆栈空间分配区别:
- 栈(操作系统) :由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;
简单数据类型存放到栈里面
- 堆(操作系统) :存储复杂类型(对象) , 一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。
复杂数据类型存放到堆里面
js里面没有堆和栈
4.3 简单类型和 复杂类型的内存分配
//简单数据类型null 返回的是个空的对象,object
var timer = null;
console .log(typeof timer);//object
//如果有个变量我们以后打算存储为对象,暂时没想好放啥, 这个时候就给null
// 1.简单数据类型是存放在栈里面里面直接开辟个空间存 放的是值
// 2.复杂数据类型首先在栈里面存放地址十六进制表示 然后这个地址指向堆里面的数据
4.4 简单类型传参
函数的形参也可以看做是一个变量 ,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈.
空间里的值复制了一份给形参 ,那么在方法内部对形参做任何修改,都不会影响到的外部变量。
4.5 复杂类型传参
函数的形参也可以看做是一个变量。当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。