JavaScript基础(3)

作用域

作用域:变量可以起作用的范围。

全局变量和局部变量
  • 全局变量
    在任何地方都可以访问到的变量就是全局变量,对应全局作用域
  • 局部变量
    只在固定的代码片段内可以访问到的变量,最常见的例如函数的内部。对应局部作用域(函数作用域)
    不使用var声明的变量是全局变量,不推荐使用
    变量退出作用域之后会销毁,全局变量关闭网页或浏览器才会销毁
块级作用域

任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域
将这样的所有作用域列出来,可以有一个结构:函数内指向函数外的链式结构,就称作作用域

// 案例1:
function f1() {
    function f2() {
    }
}

var num = 456;
function f3() {
    function f4() {    
    }
}

在这里插入图片描述

// 案例2
function f1() {
    var num = 123;
    function f2() {
        console.log(num); 
    }
    f2();
}
var num = 456;
f1();

在这里插入图片描述

预解析

JavaScript代码的执行是由浏览器中的JavaScript解析器来执行。JavaScript解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程
预解析过程:

  1. 把变量的声明提升到当前作用域的最前面,只会提升声明,不会提升赋值
  2. 把函数的声明提升到当前作用域的最前面,只会提升声明,不会调用
  3. 先提升var,再提升function
    JavaScript的执行过程
// 案例1
var a = 25;
function abc() {
  alert(a); 
  var a = 10;
}
abc();


// 案例2
console.log(a);
function a() {
  console.log('aaaaa');
}
var a = 1;
console.log(a);
变量提升
  • 变量提升
    定义变量的时候,变量的声明会被提升到作用域的最上面,变量的赋值不会提升
  • 函数提升
    JavaScript解析器首先会把当前作用域的函数声明提前到整个作用域的最前面
// 1、-----------------------------------
var num = 10;
fun();
function fun() {
  console.log(num);
  var num = 20;
}
//2、-----------------------------------
var a = 18;
f1();
function f1() {
  var b = 9;
  console.log(a);
  console.log(b);
  var a = '123';
}
// 3、-----------------------------------
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);
}
 <script>
        var num = 12;  //全局作用域 0级作用域链
        function f1() {
            num = 15;    // 局部作用域 1级作用链
            function f2() {
                console.log(num);// 局部作用域 1级作用链
            }
            f2();
        }
        f1();
        console.log(num);
    </script>
对象

JavaScript中的对象其实就是生活中对象的一个抽象
JavaScript的对象是无序属性的集合,其属性可以包含基本值、对象或函数。对象就是一组没有顺序的值。我们可以把JavaScript中的对象想象成键值对,其中值可以是数据和函数。
对象行为和特征
特征***属性 行为-----方法

  • 对事物的特征在对象中用属性来表示。
  • 事物的行为在对象中用方法来表示。
对象创建方式

字面量:11 ‘abc’ true [] {} 等

var o = {
  name: 'zs,
  age: 18,
  sex: true,
  sayHi: function () {
    console.log(this.name);
  }
};

newObject()创建对象

var person = new Object();
person.name = 'zs';
person.age = 18;
person.sayHi: function () {
    console.log(this.name);
  }

工厂函数创建对象

function createPerson(name, age, job) {
  var person = new Object();
  person.name = name;
  person.age = age;
  person.job = job;
  person.sayHi = function(){
    console.log('Hello,everyBody');
  }
  return person;
}
var p1 = createPerson('张三', 22, 'actor');
  • 自定义构造函数
function Person(name, age, job){
  this.name = name;
  this.age = age;
  this.job = job;
  this.sayHi = function(){
  	console.log('Hello,everyBody');
  }
}
var p1 = new Person('张三', 22, 'actor');
属性和方法

如果一个变量属于一个对象所有,那么该变量就可以称之为该对象的一个属性,属性一般是名词,用来描述事物的特征
如果一个函数属于一个对象所有,那么该函数就可以称之为该对象的一个方法,方法是动词,描述事物的行为和功能

new关键字

构造函数,是一种特殊的函数。主要用来字创建对象时初始化对象,即为对象成员变量赋初始值,总与new运算符一起使用在创建对象的语句中。

  • 构造函数用于创建一类对象,首字母要大写。
  • 构造函数要和new一起使用才有意义。
    new在执行时会做四件事
  • new会让内存中创建一个空对象
  • new会让this指向这个新对象
  • 执行构造函数 目的:给这个新对象加属性和方法
  • new会返回这个新对象
this详解

JavaScript中的this指向:

  1. 函数在定义的时候this是不确定的,只有在调用的时候才可以确定
  2. 一般函数直接执行,内部this指向全局window
  3. 函数作为一个对象的方法,被该对象所调用,那么this指向的是该对象
  4. 构造函数中的this其实是一个隐式对象,类似一个初始化的模型,所有方法和属性都挂载到这个隐式对象身上,后通过new关键字来调用,从而实现实例化
对象的使用
遍历对象的属性

通过for…in 语法可以遍历一个对象

var obj = {};
for (var i = 0; i < 10; i++) {
  obj[i] = i * 2;
}
for(var key in obj) {
  console.log(key + "==" + obj[key]);
}
删除对象的属性
function fun() { 
  this.name = 'mm';
}
var obj = new fun(); 
console.log(obj.name); // mm 
delete obj.name;
console.log(obj.name); // undefined
简单类型和复杂类型的区别

基本类型又叫做值类型,复杂类型又叫做引用类型
值类型:简单数据类型,基本数据类型,在存储时,变量中存储的是值本身,因此叫做值类型。
引用类型:复杂数据类型,在存储是,变量中存储的仅仅是地址(引用),因此叫做引用数据类型。

  • 堆和栈
    堆栈空间分配区别:
  1. 栈(操作系统):由操作系统自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈;
  2. 堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收,分配方式到是类似于链表。
    注意:JavaScript中没有堆和栈的概念,此处我们用堆和栈
基本类型在内存中的存储

在这里插入图片描述

复杂类型在内存中的存储

在这里插入图片描述

基本类型作为函数的参数

在这里插入图片描述

复杂类型作为函数的参数

在这里插入图片描述

内置对象

JavaScript中的对象分为3种:内置对象、浏览器对象、自定义对象
JavaScript提供多个内置对象:Math/Array/Number/String/Boolean
对象只有带有属性和方法的特殊数据类型

Math对象

Math不是构造函数,它具有数学常数和函数的属性和方法,都是以静态成员的方式提供
跟数学相关的运算来找Math中的成员(求绝对值、取整)
演示:Math.PI、Math.random()、Math.floor()/Math.ceil()、Math.round()、Math.abs() 、Math.max()

Math.PI						// 圆周率
Math.random()				// 生成随机数
Math.floor()/Math.ceil()	 // 向下取整/向上取整
Math.round()				// 取整,四舍五入
Math.abs()					// 绝对值
Math.max()/Math.min()		 // 求最大和最小值

Math.sin()/Math.cos()		 // 正弦/余弦
Math.power()/Math.sqrt()	 // 求指数次幂/求平方根

案例:

    <script>
        // - 求10-20之间的随机数  [10, 20]   整数
        // Math.random()  ->  [0, 1)  小数
        // Math.random() * 20   ->   [0, 20)  包含小数部分
        // Math.random() * (20 - 10)  -> [0, 10)  包含小数部分
        // Math.random() * (20 - 10) +  10 -> [10, 20)  包含小数部分
        // 求10-20之间的随机数
        var a = 10;
        var b = 20;
        // math.random() 范围在[0,1)
        console.log(parseInt(Math.random() * (b - a) + a));
        // 随机生成颜色RGB  [0,255]
        function randomRgb(min, max) {
            var color1 = Math.floor(Math.random() * (max - min + 1) + min);
            var color2 = Math.floor(Math.random() * (max - min + 1) + min);
            var color3 = Math.floor(Math.random() * (max - min + 1) + min);
            return 'rgb(' + color1 + ',' + color2 + ',' + color3 + ')';
        }
        // 点击按钮调用随机生成颜色方法
        function fn() {
            var a = randomRgb(0, 255);
            // 改变body的背景
            document.body.style.backgroundColor = a;
        }

        console.log(a);
        // 模拟min()和max()
        var MyMath = {
            max: function () {
                var max = arguments[0];
                for (let i = 1; i < arguments.length; i++) {
                    if (max < arguments[0]) {
                        max = arguments[i];
                    }

                }
                return max;
            }
        }
        console.log(MyMath.max(20, 20, 30, 40))
    </script>

math不是构造函数,静态成员直接math.random() date是构造函数需要new date()

Date对象

创建Date实例用来处理日期和时间。Date对象基于1970年1月1日。

// 获取当前时间,UTC世界时间,距1970年1月1日(世界标准时间)起的毫秒数
var now = new Date();
console.log(now.valueOf());	// 获取距1970年1月1日(世界标准时间)起的毫秒数

Date构造函数的参数
1. 毫秒数 1498099000356		new Date(1498099000356)
2. 日期格式字符串  '2015-5-1'	 new Date('2015-5-1')
3. 年、月、日……				  new Date(2015, 4, 1)   // 月份从0开始

//获取日期的毫秒形式
var now = new Date();
// valueOf用于获取对象的原始值
console.log(date.valueOf())	

// HTML5中提供的方法,有兼容性问题
var now = Date.now();	

// 不支持HTML5的浏览器,可以用下面这种方式
var now = + new Date();			// 调用 Date对象的valueOf() 

//日期格式化方式
toString()		// 转换成字符串
valueOf()		// 获取毫秒值
// 下面格式化日期的方法,在不同浏览器可能表现不一致,一般不用
toDateString()
toTimeString()
toLocaleDateString()
toLocaleTimeString()

//获取日期指定部分
getTime()  	  // 返回毫秒数和valueOf()结果一样,valueOf()内部调用的getTime()
getMilliseconds() 
getSeconds()  // 返回0-59
getMinutes()  // 返回0-59
getHours()    // 返回0-23
getDay()      // 返回星期几 0周日   6周6
getDate()     // 返回当前月的第几天
getMonth()    // 返回月份,***从0开始***
getFullYear() //返回4位的年份  如 2016

案例:

   <script>
        // 写一个函数,格式化日期对象,返回yyyy-MM-dd HH:mm:ss的形式
        function formatDate(data) {
            // 先判断是不是date格式
            if (!(data instanceof Date)) {
                console.error('格式不正确!')
                return;
            }
            // 获取时间日期
            var year = data.getFullYear(),
                month = data.getMonth() + 1,
                day = data.getDate(),
                hour = data.getHours(),
                minute = data.getMinutes(),
                second = data.getSeconds();
            // 判断是否大于10
            month = month < 10 ? '0' + month : month;
            day = day < 10 ? '0' + day : day;
            hour = hour < 10 ? '0' + hour : hour;
            minute = minute < 10 ? '0' + minute : minute;
            second = second < 10 ? '0' + second : second;
            return year + '-' + month + '-' + day + '-' + '' + hour + ':' + minute + ':' + second;
        }
        var test = new Date();
        var data = formatDate(test);
        console.log(data);
        // var test = new Date(2000, 3);
        // var data = formatDate(test);
        // console.log(data);


        // 计算两个时间段的差
        var d1 = new Date();
        var d2 = new Date(1945 - 4 - 5);
        console.log(d1 - d2);
    </script>
Array对象

创建数组对象的两种方式

  • 字面量方式
  • new Array()
// 1. 使用构造函数创建数组对象
// 创建了一个空数组
var arr = new Array();
// 创建了一个数组,里面存放了3个字符串
var arr = new Array('zs', 'ls', 'ww');
// 创建了一个数组,里面存放了4个数字
var arr = new Array(1, 2, 3, 4);


// 2. 使用字面量创建数组对象
var arr = [1, 2, 3];

// 获取数组中元素的个数
console.log(arr.length);
  • 检测一个对象是否是数组
    instanceof
    Array.isArray()
    函数的参数,如果要求是一个数组的话,可以用这种方式来进行判断
  • toString()/valueOf()
    toString() 把数组转换成字符串,逗号分隔每一项
    valueOf() 返回数组对象本身
    数组常用方法:push()、shift()、unshift()、reverse()、sort()、splice()、indexOf()
// 1 栈操作(先进后出)
push()
pop() 		//取出数组中的最后一项,修改length属性
// 2 队列操作(先进先出)
push()
shift()		//取出数组中的第一个元素,修改length属性
unshift() 	//在数组最前面插入项,返回数组的长度
// 3 排序方法
reverse()	//翻转数组
sort(); 	//即使是数组sort也是根据字符,从小到大排序
// 带参数的sort是如何实现的?
// 4 操作方法
concat()  	//把参数拼接到当前数组
slice() 	//从当前数组中截取一个新的数组,不影响原来的数组,参数start从0开始,end从1开始
splice()	//删除或替换当前数组的某些项目,参数start, deleteCount, options(要替换的项目)
// 5 位置方法
indexOf()、lastIndexOf()   //如果没找到返回-1
// 6 迭代方法 不会修改原数组(可选)
every()、filter()、forEach()、map()、some()
// 7 方法将数组的所有元素连接到一个字符串中。
join()
  • 清空数组
    // 方式1 推荐
    arr = [];
    // 方式2
    arr.length = 0;
    // 方式3
    arr.splice(0, arr.length);
    案例:
 <script>
        var a = [1, 3, 7, 5];
        // 栈操作(先进后出)
        // push 参数会有多个,将来都会添加都数组最后
        a.push(4, 5);
        console.log(a);
        // pop返回数组的最后一个元素,并且会修改数组的长度就像截取字符串
        var last = a.pop();
        console.log(last);
        console.log(a.length);
        console.log(a);

        // 队列操作(先进先出)
        var array = [1, 2, 3];
        array.push(4);
        // 返回数组第一个元素
        var first = array.shift();
        console.log(first);
        console.log(array);
        // 在前面添加一个元素
        var first2 = array.unshift(0);
        console.log(array);
        // 3.排序方法
        //   reverse()  翻转数组
        var a1 = [1, 2, 3, 4, 5, 6];
        console.log(a1);
        var a2 = a1.reverse();
        console.log(a2);
        //sort 排序
        var a3 = [1, 8, 5, 0, 3];
        console.log(a3);
        var a4 = a3.sort();
        console.log(a4);
    </script>
基本包装类型
// 下面代码的问题?
// s1是基本类型,基本类型是没有方法的
var s1 = 'zhangsan';
var s2 = s1.substring(5);

// 当调用s1.substring(5)的时候,先把s1包装成String类型的临时对象,再调用substring方法,最后销毁临时对象, 相当于:
var s1 = new String('zhangsan');
var s2 = s1.substring(5);
s1 = null;
// 创建基本包装类型的对象
var num = 18;  				//数值,基本类型
var num = Number('18'); 	//类型转换
var num = new Number(18); 	//基本包装类型,对象
// Number和Boolean基本包装类型基本不用,使用的话可能会引起歧义。例如:
var b1 = new Boolean(false);
var b2 = b1 && true;		// 结果是什么
String对象
  • 字符串的不可变
    var str = ‘abc’;
    str = ‘hello’;
    // 当重新给str赋值的时候,常量’abc’不会被修改,依然在内存中
    // 重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变
    // 由于字符串的不可变,在大量拼接字符串的时候会有效率问题
  • 创建字符串对象
    var str = new String(‘Hello World’);
    // 获取字符串中字符的个数
    console.log(str.length);
  • 字符串对象的常用方法
// 1 字符方法
charAt()    	//获取指定位置处字符
charCodeAt()  	//获取指定位置处字符的ASCII码
str[0]   		//HTML5,IE8+支持 和charAt()等效
// 2 字符串操作方法
concat()   		//拼接字符串,等效于+,+更常用
slice()    		//从start位置开始,截取到end位置,end取不到
substring() 	//从start位置开始,截取到end位置,end取不到
substr()   		//从start位置开始,截取length个字符
// 3 位置方法
indexOf()   	//返回指定内容在元字符串中的位置
lastIndexOf() 	//从后往前找,只找第一个匹配的
// 4 去除空白   
trim()  		//只能去除字符串前后的空白
// 5 大小写转换方法
to(Locale)UpperCase() 	//转换大写
to(Locale)LowerCase() 	//转换小写
// 6 其它
search()
replace()
split()
fromCharCode()
// String.fromCharCode(101, 102, 103);	 //把ASCII码转换成字符串

// JavaScript 组成: ECMAScript BOM DOM
// ECMAScript:变量 注释 数据类型 类型转换 操作符 流程控制语句(判断和循环) 数组 对象 构造函数 内置对象
// JavaScript中的对象有三种:自定义对象、内置对象、浏览器对象
// ECMAScript中的对象: 自定义对象、内置对象
//
// 内置对象:Math/Array/Date…
//
// 最常用的属性和方法
//
// 查文档:MDN
案例:

  <script>
        // 1.charAt()   获取指定位置处字符
        // 2.charCodeAt()  获取指定位置处字符的ASCII码
        // 3.str[0]    HTML5,IE8+支持和charAt()等效
        var s = 'abcdef';
        console.log(s.charAt(0));
        for (let i = 0; i < s.length; i++) {
            console.log(s.charAt(i));
        }
        console.log(s.charCodeAt(0));
        // 字符串操作方法
        // concat()     拼接字符串,等效于+,+更常用
        // slice()      从start位置开始,截取到end位置,end取不到
        // substring()    从start位置开始,截取到end位置,end取不到
        // substr()  从start位置开始,截取length个字符

        // 位置方法
        // indexOf()       返回指定内容在元字符串中的位置
        // lastindexOf()    从后往前找,只找一个匹配的
        var s = '我是程序猿一只';
        // 第一个参数,截取的开始位置 0 1 2
        // 第二个参数,截取的长度
        // var newStr = s.substr(2, 2);
        // console.log(newStr);

        // // 'jdafjfsdfhfhs'  查找字符串中所有j出现的位置
        // var a = 'jdafjfsdfhfhs';
        // // 当查找不到的时候返回的是-1
        // console.log(a.indexOf('j', 0));
        // var index = -1;
        // do {
        //     index = a.indexOf('j', index + 1);
        //     if (index !== -1) {
        //         console.log(index);
        //     }
        // } while (index !== -1);

        var s = 'abcoefoxyozzopp';

        //  abc!efoxyozzopp
        //  只会替换第一个找到的字符串
        // s = s.replace('o', '!');
        // console.log(s);
        // 
        var index = -1;
        do {
            index = s.indexOf('o', index + 1);

            if (index !== -1) {
                // 替换
                s = s.replace('o', '!');
            }
        } while (index !== -1);
        console.log(s);

        // 去除空白
        // trim()   只能去除字符串中的位置

        //trim() 只可以去除字符串前后的空格
        var s2 = '   abc    vyx   xyx   ';
        console.log(s2.trim());
        //  思路1 可以把字符串中的所有 空格 字符串 用replace替换成 '' 空字符串
        // 思路2 使用split简化
        var str = 'a,b,c,d';
        var arr = str.split(',');
        console.log(arr.join('!'));
        var arr1 = s2.split(' ');
        console.log(arr1.join(''));

        // 大小写转换方法
        // to(local) UpperCase()   转换大写
        // to(local)LowerCase()    转换小写
        // 其他
        // search()  寻找         replace()    替换             split() 全部替换   要join() 方法
        // 获取url中?后面的内容
        // 例如:http://www.itheima.com/login?name=zs&age=18&a=1&b=2

        var url = 'http://www.itheima.com/login?name=zs&age=18&a=1&b=2';

        // console.log(url.substr(2));
        // var index = url.indexOf('?') + 1;
        // console.log(url.substr(index));


        // {
        //   name: 'zs',
        //   age: 18
        // }

        // 获取url后面的参数
        function getParams(url) {
            // 获取? 后面第一个字符的索引
            var index = url.indexOf('?') + 1;
            // url中?后面的字符串 name=zs&age=18&a=1&b=2
            var params = url.substr(index);
            // 使用& 切割字符串 ,返回一个数组
            var arr = params.split('&');
            var o = {};
            // 数组中每一项的样子 key = value
            for (var i = 0; i < arr.length; i++) {
                var tmpArr = arr[i].split('=');
                var key = tmpArr[0];
                var value = tmpArr[1];

                o[key] = value;
            }
            return o;
        }

        var obj = getParams(url);
        console.log(obj);

        console.log(obj.name);
        console.log(obj.age);


    </script>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值