一、预解析
1、理论解释
1.我们js引擎运行js分为两步:预解析 代码执行
(1).预解析js引擎会把js里面所有的 var 还有function提升到当前作用域的最前面
(2).代码执行按照代码书写的顺序从上往下执行
2.预解析分为变量预解析(变量提升)和函数预解析(函数提升)
(1)变量提升就是把所有的变量声明提升到当前的作用域最前面不提升赋值操作
(2)函数提升就是把所有的函数声明提升到当前作用域的最前面 不调用函数
坑1:如果先输出,再声明,那么默认会把变量声明提升到最前,但是不赋值
坑2:函数表达式调用必须写在函数表达式下面。
举例:如果函数这样声明,那么不管在前面调用还是后面调用是没有影响的,因为默认会把函数声明放到最前面预解析。
所以不管是放在前面还是后面,默认执行的是这样的代码
2、案例解析
(1)案例1:下面代码怎么执行?结果是什么?
相当于执行了以下代码:
var num; //1.第一步变量提升
function fun() { //2.第二步函数提升
var num; //局部变量第一步变量提升
console.log(num); //函数内部代码依次执行 undefined
num = 20; //赋值
}
//接下来吧没有执行的依次罗列
num = 10; //3.第三步赋值
fun(); // 4.第四步调用函数
结果:undefined
(2)案例2:下面代码怎么执行?结果是什么?
相当于执行了以下代码:
// 相当于执行了以下代码
var num;
function fn() {
var num;
console.log(num);//undefined
num = 20;
console.log(num);//20
}
num = 10;
fun();
结果:undefined 20
(3)案例3:下面代码怎么执行?结果是什么?
相当于执行了以下代码:
// 相当于执行以下代码
var a;
function f1() {
var b;
var a;
b = 9;
console.log(a);//undefined
console.log(b);//9
a = '123';
}
f1();
结果:undenfined 9
(4)案例4:下面代码怎么执行?结果是什么?
相当于执行了以下代码:
function f1() {
// var a = b = c = 9;
//var a = 9; b = 9; c = 9;相当于只var a;b和c直接赋值,当做全局变量看。
//集体声明:var a = 9, b = 9, c = 9这样写才相当于var a;var b;var c
var a;
a = b = c = 9;
console.log(a);//9
console.log(b);//9
console.log(c);//9
}
f1();
console.log(a);//undefined
console.log(b);//9
console.log(c);//9
结果是:9 9 9 undefined 9 9
注意:var a = 9; b = 9; c = 9;相当于var a=9;b=9;c=9; b和c直接赋值,当做全局变量看。
集体声明:var a = 9, b = 9, c = 9;这样写才相当于var a;var b;var c。
所以a只是一个局部变量,外边没有声明a。函数内没有被var的是全局变量。
二、对象
1、对象
(1)什么是对象?
在JavaScript中,对象是一组无序的相关属性和方法的集合,所有的事物都是对象,例如字符串、数值、数组、函数等。
对象是由属性和方法组成的。
·属性:事物的特征,在对象中用属性来表示(常用名词)
方法:事物的行为,在对象中用方法来表示(常用动词)
(2)为什么需要对象?
2、创建对象的三种方式
(1)利用字面量创建对象
1.里面的属性或方法采用键值对的形式,即属性名:属性值
2.多个属性或方法中间用逗号隔开
3.方法冒号后面跟的是一个匿名函数
var dog = {
name: '可可',
age: '5岁',
type: '阿拉斯加',
color: '棕红色',
skills: function () {
console.log('汪汪汪');
console.log('表演电影');
}
}
调用对象:
1.使用对象名.属性名;;
2.使用对象名[‘属性名’];
3.调用对象内的方法:对象名.方法名();
//调用对象
console.log(dog.name);
console.log(dog['name']);//这种调用,不管什么数据类型都必须要加单引号
dog.skills();
(2) 变量、属性、函数、方法的区别
变量和属性:
总结:
变量:单独声明赋值,单独存在
属性:对象里面的变量称为属性,不需要声明,用来描述该对象的特征·
函数:单独存在的,通过“函数名0”的方式就可以调用·
方法:对象里面的函数称为方法,方法不需要声明,使用“对象方法名0”的方式就可以调用,方法用来描述该对象的行为和功能。
(2)利用new Object创建对象
1、我们是利用等号=赋值的方法
2、每个属性和方法之间用分号结束添加对象的属性和方法
//利用 new object创建对象
var obj=new object();//创建了一个空的对象
obj.uname= '张三疯';
obj.age = 18;
obj.sex= '男';
obj.sayHi = function() {
console.log('hi~');
}
// 我们是利用等号=赋值的方法
// 每个属性和方法之间用分号结束添加对象的属性和方法
调用方法是一致的:
console.log(obj.name);
console.log(obj['name']);
obj.sayHi();
(3)利用构造函数创建对象
我们为什么需要使用构造函数?
就是因我们前面两种创建对象的方式一次只能创建一个对象。因为我们一次创建一个对象,里面很多的属性和方法是大量相同的。
因此我们可以利用函数的方法重复这些相同的代码。我们就把这个函数称为构造函数。
又因为这个函数不一样,里面封装的不是普通代码,而是对象。构造函数就是把我们对象里面一些相同的属性和方法抽象出来封装到函数里面。
构造函数创建对象的语法格式:
function 构造函数名() {
this.属性 = 值;
this.方法 = function() {}
}
new 构造函数();//调用
function Star(name,sex,age) {
this.name = name;
this.sex = sex;
this.age = age;
this.sing = function(sang) {
console.log(sang);
}
}
var ldh = new Star('刘德华','男',28);//调用函数返回的是一个对象object
console.log(typeof ldh);//object
console.log(ldh.name);
console.log(ldh['sex']);
ldh.sing('冰雨');
//1.构造函数名字首字母要大写
// 2.我们构造函数不需要return就可以返回结果
// 3.调用构造函数必须使用new
// 4.我们只要new Star()调用函数就创建一个对象 ldh
// 5. 我们的属性和方法前面必须添加this{}
注意:
1.构造函数名字首字母要大写
2.我们构造函数不需要return就可以返回结果
3.调用构造函数必须使用new
4.我们只要new Star()调用函数就创建一个对象 ldh
5. 我们的属性和方法前面必须添加this{}
例如创建一个后裔:
function Hero(name,type,blood) {
this.name = name;
this.type = type;
this.blood = blood;
this.attack = function(action) {
console.log(action);
}
}
var houyi = new Star('后裔','射手',1000);
houyi.attack('远战');
console.log(houyi.name);
console.log(houyi['type']);
(4)new关键字执行对象过程
1.new构造函数可以在内存中创建了一个空的对象
2.this就会指向刚才创建的空对象
3.执行构造函数里面的代码给这个空对象添加属性和方法
4.返回这个对象
3、遍历对象
使用for……in遍历对象。如果我想获取下面这个对象的全部属性名和属性值:
var dog = {
name: '可可',
age: 5,
type: '阿拉斯加犬',
color: '棕红色',
skills: function () {
console.log('bark');
console.log('showFilm');
}
}
那么只需要这样:
for (var k in dog) {
console.log(k); //k是得到属性名
console.log(dog[k]); 对象名[k]是得到属性值
}
这里k是得到属性名,对象名[k]是得到属性值。