JavaScript(三):作用域、预解析、对象

一、作用域

全局作用域:在整个script标签下或者在一个单独的js文件中
局部作用域:在函数内部就是局部作用域,这个代码的名字只在函数内部起作用
全局变量:
在这里插入图片描述
局部变量:
在这里插入图片描述
全局变量和局部变量的区别:
在这里插入图片描述
作用域链:内部函数访问外部函数的变量,采取的是链式查找的方式来决定取哪个值。总结来说就是:一层一层往外找,采用就近原则。这个还是比较简单的。

var num = 10;
        function fu() {
            var num = 20;
            function fun() {
                console.log(num);
            }
            fun();
        }
        fu();  //20

二、预解析

1.理论

在这里插入图片描述
举例1:如果先输出,再声明,那么默认会把变量声明提升到最前,但是不赋值
在这里插入图片描述
举例2:这里虽然是声明函数,但是是变量提升,也就是先声明fun变量,再给fun函数,所以会报错。像这种一般都是先预解析声明变量,然后后面的代码照抄。
在这里插入图片描述
举例3:如果函数这样声明,那么不管在前面调用还是后面调用是没有影响的,因为默认会把函数声明放到最前面预解析
在这里插入图片描述
所以这个例子默认是这样的代码:
在这里插入图片描述

2.案例

(1)案例1:下面代码怎么执行?结果是什么?

var num = 10;
    fun();  
    function fun() {
        console.log(num);
        var num = 20;
    }

其实是相当于执行了以下代码:

   var num;  //1.第一步变量提升
    function fun() {   //2.第二步函数提升
        var num; //局部变量第一步变量提升
        console.log(num);  //函数内部代码依次执行
        num = 20;  //赋值
    }
    num = 10;   //3.第三步赋值
    fun();  // 4.第四步调用函数

所以结果应该是undefined。

(2)案例2:下面代码怎么执行?结果是什么?

    //预解析案例2
    var num = 10;
    function fn() {
        console.log(num);
        var num = 20;
        console.log(num);
    }
    fn();
    //案例2相当于执行了以下代码
    var num;
    function fn() {
        var num;
        console.log(num);  //undefined
        num = 20;
        console.log(num);  //20
    }
    num = 10;
    fn();

结果应该是undefined,20

(3)案例3:下面代码怎么执行?结果是什么?

        //预解析案例3
        var a = 18;
        f1();
        function f1() {
            var b = 9;
            console.log(a);
            console.log(b);
            var a = '123';
        }
    //案例3相当于执行了以下代码
    var a;
    function f1() {
        var b;
        var a;
        b = 9;
        console.log(a);
        console.log(b);
        a = '123';
    }
    f1();

结果应该是undefined, 9

(4)案例4:下面代码怎么执行?结果是什么?

这个有点小小的难度,这里需要注意,var a = b = c = 9; 相当于var a = 9; b = 9; c = 9;
var a = 9, b = 9, c = 9;相当于 var a = 9; var b = 9; var c = 9;

    //预解析案例4,这个有点意思
    f1();
    console.log(c);
    console.log(b);
    console.log(a);
    function f1() {
        var a = b = c = 9;  //var a = 9; b = 9; c = 9;
        //集体声明:var a = 9, b = 9, c = 9
        console.log(a);
        console.log(b);
        console.log(c);
    }
    //案例4相当于执行了下面这个代码
    function f1() {
        var a = 9;  //局部变量
        b = 9; //全局变量
        c = 9; //全局变量
        console.log(a);
        console.log(b);
        console.log(c);
    }
    f1();
    console.log(a);
    console.log(b);
    console.log(c);

因为b,c没有var,所以是全局变量,a var了一下子,所以应该是局部变量,只在f1函数里有用,那么这样的话,结果就一目了然了,999,报错,99。这里为什么第二个a会报错呢,是因为外边没有声明a,也没有赋值,如果只有var a不赋值才是undefined。所以这个案例的关键一个是函数内不var的是全局变量,还有一个关键就是var a = b = c = 9; 相当于var a = 9; b = 9; c = 9;

三、对象

什么是对象?
在这里插入图片描述
为什么需要对象?
在这里插入图片描述

1.创建对象的三种方式,调用对象

(1)利用字面量(花括号)创建对象

1.里面的属性或方法采用键值对的形式,即属性名:属性值
2.多个属性或方法中间用逗号隔开
3.方法冒号后面跟的是一个匿名函数

	var obj = {
	    name: '张三',
	    age: 18,
	    sex: '男',
	    sayHi: function() {
	        console.log('Hi~ o(* ̄▽ ̄*)ブ');
	    }
	}

(2)如何调用对象?

1.使用对象名.属性名;;
2.使用对象名[‘属性名’];
3.调用对象内的方法:对象名.方法名();

	var dog = {
	    name: '可可',
	    age: 5,
	    type: '阿拉斯加犬',
	    color: '棕红色',
	    skills: function () {
	        console.log('bark');
	        console.log('showFilm');
	    }
	}
	
	//调用对象
	console.log(dog.name);
	console.log(dog['name']);//这种调用,不管什么数据类型都必须要加单引号
	dog.skills();

(3)利用new object创建对象

注意对比和字面量创建的不同,这个是用等号赋值,分号隔开,Object的O要大写

	//使用new object创建对象
	var obj = new Object();
	obj.name = '可可';
	obj.age = 5;
	obj.type = '阿拉斯加犬';
	obj.color = '棕红色';
	obj.skills = function () {
	    console.log('bark');
	    console.log('showFilm');
	}

调用没啥区别

//调用对象
console.log(obj.name);
console.log(obj['name']);
obj.skills();

(4)构造函数创建对象

当我们要构建好多对象,他们都有相同的属性的时候,就可以把这些属性封装到函数里
构造函数和对象就相当于汽车和奥迪之间的关系,对象也可以叫实例
构造函数创建对象的语法格式:

	//构造函数创建对象
	function 构造函数名() {
	    this.属性名 = 属性值;
	    this.方法名 = function() {}
	}
	// 调用
	new 构造函数名();

我们约定,使用函数创建对象时,函数名首字母必须大写
举例,构造一个王者荣耀的英雄函数:其中包括名字,类型,血量,攻击方式
这里面的this指的是我们调用的对象,比如下面的houyi和luban

	function Hero(name, type, blood) {
	    this.name = name;
	    this.type = type;
	    this.blood = blood;
	    this.attack = function(attack) {
	        console.log(attack);
	    }
	}

有个这个函数,那么我们就可以通过调用它,返回一个对象,比如调用构造函数来创造名为houyi的对象

	var houyi = new Hero('后羿', '射手', 1000); //调用函数返回的是一个对象
	console.log(typeof houyi);  //object

调用构造函数来创造名为luban的对象:

   //调用构造函数来创造名为luban的对象
    var luban = new Hero('luban', 'sheshou', 1200);

那么这样,我们就可以去查看对象里的属性:

	console.log(houyi.name);
	console.log(houyi['blood']);
	console.log(luban.name);
	console.log(luban.type);

或者去调用方法:

	houyi.attack('远程');
	luban.attack('远程');
构造函数创建对象的几个注意点:

1.构造函数首字母必须大写,这是约定
2.构造函数不需要return,就可以返回结果
3.调用构造函数创建对象必须要有new
4.和普通函数相比,其实就多了this和new
5.注意这里的形参和实参

2. 构造函数创建对象中new关键字的执行过程

1.在内存中创建一个新的空对象
2.让this指向这个空对象,先认一下是不是当前对象
3.执行构造函数内的代码,给这个新对象添加属性和方法(把该有的都扔给他)
4.返回这个新对象(所以说为什么不用return,new就搞定了)
在这里插入图片描述

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]是得到属性值

4.封装一个数学对象

注意属性和属性之间的逗号别丢了,方法和方法之间也要有逗号
这里主要复习一下以前的内容,包括arguments,还有创建对象调用对象等等

   //利用对象来封装自己的数学对象  里面有PI和最大值,最小值
    var myMath = {
        PI: Math.PI,
        max: function () {
            max = arguments[0];
            for (var i = 1; i < arguments.length; i++) {
                if (arguments[i] > max) {
                    max = arguments[i];
                }
            }
            return max;
        },  //这里别忘了加逗号!!
        min: function () {
            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(23, 35, 46, 34, 2));
    console.log(myMath.min(23, 35, 46, 34, 2));

5.删除对象中某个属性

最常用的,delete运算符

delete object.property;
delete object['property']

6.对象中某个键值设置为读取某个变量

加上[]

   const dj = 'name';
    const obj = {
        [dj]: 'zzy',
        age: 18
    }
    console.log(obj) //{name: 'zzy', age: 18}
  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值