前端--阶段笔记(三) JS编程基础 06

作用域内置对象和数据类型

作用域

作用域:代码变量在某个范围内起作用和效果。目标是提高可靠性,并减少命名冲突。

1.全局作用域:整个script标签都是一个单独的js文件

​ 局部作用域就是指在函数内部是起作用的。

2.全局变量,有两种是全局变量:1全局作用域下声明的变量为全局的变量,2或者在函数内部没声明直接赋值的变量。

js es6 之前没有块级作用域,
只有全局与局部(函数作用域)两种作用域。
在es6才新增块级作用域。

块级作用域

{} 有花括号包含的部分就叫做块级作用域。

注意!有{}的不一定是函数,也可能是,if 或者for。

下面的这个例子就不是写的函数的例子。

if(true){
    
    
  var num = 123;
  console.log(num); //123
}
console.log(num);   //不会报错

如果是java代码

if(true){
    
    
  int num = 123;
  system.out.print(num);  // 123
}
system.out.print(num);    //报错

变量作用域

作用域链,链式查找,就近原则

1 .特殊情况下,在函数内不声明即使用的变量,是全局变量(不建议使用)

2 .局部变量只能在该函数内部使用

局部变量只能在该函数内部使用

js在es6前没有块级作用域

那么一个函数内部的变量就可以被外部调用,这和前面局部变量只能在该函数内使用时相互冲突的,这是怎么回事?

解答:函数内部的局部变量不能用在外部调用,只能在函数内部使用。es6之前没有的是块级作用域,块级作用域中定义的变量可以在块级以外使用,块级作用域不是函数作用域,两码事,所以不冲突。

js引擎预解析

js运行两个步骤:

1.预解析

2.运行

预解析会把代码中所有var和function提升到当前作用域最前面。

作用域分为全局作用域和局部作用域。

预解析分为变量预解析和函数预解析

1 .变量预解析(变量提升):只做声明不做赋值。

2 .函数表达式声明函数

var fun = function () {
    
    

console.log('print');

}

函数表达式形式定义的函数,调用必须写在函数下面,不然报错。

例:

fn();
var  fn = function() {
    
    
    console.log('想不到吧');
}

执行步骤:

1.隐函数定义式中的变量fn 先提升到代码最前端,此时fn未定义,为undefined

2.然后fn();调用了fn 所以报错。

案例:

var a = b = c = 9;

相当于var a = 9; c = 9; b = 9; b c没有声明就已经赋值,所以b,c是全局变量。
如果要实现abc 一次赋值并属于局部变量,需要写为:

var a = 0,b = 0,c = 0;

对象

万物皆对象,但必须具象,具有唯一性。不能是某些合集或者不确定的,比如老师,女朋友。

复杂数据类型 Object(对象)
ECMAScript中的对象其实就是一组数据(属性)和功能(方法)的集合。

属性:事物的特征,在对象中用属性来表示(名词)
方法:事物的行为,在对象中用方法来表示(动词)

用对象的表示方法可以结构清晰更强大,
为了让更好地存储一组数据,对象应运而生。

对象中为每项数据设置了属性名称,可以访问数据更语义化,数据结构清晰,表意明显,方便开发者使用。

多个属性或者方法中间用逗号隔开!!!

三种办法创建对象:

1.利用字面量创建
2.利用new object创建
3.利用构造函数创建

1.字面量创建

	var obj = {
    
    
		username: "charlotte",
		age:18,
		sex:female,
		sayHi: function() {
    
    
		console.log('hi~');
		}
	}

​ 花括号内包含属性与方法 采用键值对的方式存储

​ 键对应属性名,值对应属性值;

​ 包括函数也是这样声明,名字:函数

调用对象属性:

​ 方法1

​ 对象名.属性名

​ console.log(obj.name);

​ 方法2

​ 对象名[‘属性名’]

​ console.log(obj[‘age’]);

调用对象方法:

​ 对象名.方法名() //注意 多加了括号。

​ obj.sayHi();

2.newObject创建对象

	var obj = new Object();
	obj.uname = 'nancy';
	obj.sex = female;

	obj.sayHi = function() {
    
    
	console.log('Hi~');
	}

3.构造函数方式创建对象

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

1.找到相同属性封装进去

function 构造函数名(形参1,形参2,形参三) {
    
    
	this.属性1 = 形参1;  //注意这里是分号;
	this.属性2 = 形参2;  //注意这里是分号;
	this.属性3 = 形参3;  //注意这里是分号;
	this.方法 = function() {
    
    
	}
}

调用:

var obj = new 构造函数名(实参1,实参2,实参3)

例:

function Star(uname, sex, age) {
    
    
    this.name = uname;
    this.sex = sex;
    this.age = age;
}
   var tomCruise = new Star('tom', 'male', 58);
   console.log(tomCruise.name);

构造函数不需要return就可以返回结果。

构造函数首字母大写,注意是构造函数的那个首字母大写

new 关键字的作用

1 .在内存创建新的空对象

2 .this指向这个新对象

3 .执行构造函数里面的代码给新对象添加属性方法

4 .返回这个新对象

for in 遍历对象

for…in 语句用于遍历数组或者对象的属性(对数组或者对象的属性进行循环操作)。

for var k in
k不是固定的,但是我们习惯性写k。

for (var k in obj) {
    
    
console.log(k);//k变量,输出得到的是属性的名字不是值。
console.log(obj[k]);//obj[k] 得到 属性里面的值。
}
var arytest = ['red', 'green', 'blue', 'pink'];
for (var k in arytest){
    
    
                console.log(k);
                console.log(arytest[k]);
            }
//打印结果
0
red
1
green
2
blue
3
pink

对象是复杂数据类型object
本质是一组无序的相关属性与方法的集合
构造函数泛指一个大类
对象实指一个

内置对象

JS中对象分三类:
1 .自定义对象
2 .内置对象
3 .浏览器对象

前面两种是JS基础内容,属于ECMAscript标准规定。JS自带内置对象,供开发者使用提供常见或必要功能,内置对象最大优点就是帮助我们快速开发。第三个浏览器对象属于js独有。
提供了多个内置对象:Math,Date,Array,String等

1.math对象

math 是一个对象。所有内容都是静态的。直接使用。

Math.round四舍五入,其他数字都是四舍五入,但是.5这个数字是往整体数字大了取。
小数的情况下要多考虑。

属性、方法名 功能
Math.PI 圆周率
Math.floor() 向下取整,往小了取
Math.ceil() 向上取整,往大了取
Math.round() 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() 绝对值
Math.max()/Math.min() 求最大和最小值
Math.random() 获取范围在[0,1)内的随机值

由Math.random 得到任意区间的随机整数(返回 min(包含)~ max(包含)之间的数字)

function getRandom(min, max) {
    
    
  return Math.floor(Math.random() * (max - min + 1)) + min; 
}

2.Date日期对象

​ Date是一个构造函数(看不懂的话回去看 ‘构造函数方式创建对象’),所以必须配合别的具体对象才能使用,即需要实例化之后才能用其中的具体方法和属性。

  • 自动获取系统当前时间
var now = new Date();//Date()内没有参数返回系统时间
console.log(now);
  • 获取指定时间
var future = new Date('2019/5/1');
var future =new Date'2019-5-2';    
  • Date构造函数的方法与说明:
    在这里插入图片描述

注意:获取的月份是 0 - 11,所以要在获取的月份上 +1 才是正确时间。

  • 格式化日期年月日输出
//按照自己的格式输出时间
//先自定义一个date
var date = new Date();//Date()内没有参数,则返回系统时间
    console.log(date);
//注意 date小写,getFullYear 驼峰命名
var year = date.getFullYear();
var month = date.getMonth() + 1;
var dates = date.getDate();
var xingqi = ['星期日', '星期一', '星期二', '星期三', '星期四', '星期五', '星期六'];
var day = date.getDay();
console.log('今天是' + year + '年' + month + '月' + dates + '日' + xingqi[day]);
  • 格式化日期 时分秒的输出

    //格式化时分秒的输出
      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());
    
  • 根据不同时间做出不同反应:

        // 根据系统不同时间来判断,所以需要用到日期内置对象
        // 利用多分支语句来设置不同的图片
        // 需要一个图片,并且根据时间修改图片,就需要用到操作元素src属性
        // 需要一个div元素,显示不同问候语,修改元素内容即可
        // 1.获取元素
        var img = document.querySelector('img');
        var div = document.querySelector('div');
        // 2. 得到当前的小时数
        var date = new Date();  //由date构造函数构造出来新的对象 内部包含所有方法
        var h = date.getHours();   // 从date中通过方法 gethour 取出所需要的数据,赋值给h
        // 3. 判断小时数改变图片和文字信息
        if (h < 12) {
    
    
            img.src = 'images/s.gif';
            div.innerHTML = '亲,上午好,好好写代码';
        } else if (h < 18) {
    
    
            img.src = 'images/x.gif';
            div.innerHTML = '亲,下午好,好好写代码';
        } else {
    
    
            img.src = 'images/w.gif';
            div.innerHTML = '亲,晚上好,好好写代码';

        }
  • 通过Date获取时间戳

    1 .getTime() 返回 1970 年 1 月 1 日至今的毫秒数。

    2 .valueOf() 一样的效果。

    3 .var dat1 = +new Date();

    4 .console.log(Date.now());

案例:倒计时效果

     // 倒计时效果
        // 1.核心算法:输入的时间减去现在的时间就是剩余的时间,即倒计时 ,但是不能拿着时分秒相减,比如 05 分减去25分,结果会是负数的。
        // 2.用时间戳来做。用户输入时间总的毫秒数减去现在时间的总的毫秒数,得到的就是剩余时间的毫秒数。
        // 3.把剩余时间总的毫秒数转换为天、时、分、秒 (时间戳转换为时分秒)
        // 转换公式如下: 
        //  d = parseInt(总秒数/ 60/60 /24);    //  计算天数
        //  h = parseInt(总秒数/ 60/60 %24)   //   计算小时
        //  m = parseInt(总秒数 /60 %60 );     //   计算分数
        //  s = parseInt(总秒数%60);            //   计算当前秒数
        function countDown(time) {
    
    
            var nowTime = +new Date(); // 返回的是当前时间总的毫秒数
            var inputTime = +new Date(time); // 返回的是用户输入时间总的毫秒数
            var times = (inputTime - nowTime) / 1000; // times是剩余时间总的秒数 
            var d = parseInt(times / 60 / 60 / 24); // 天
            d = d < 10 ? '0' + d : d;
            var h = parseInt(times / 60 / 60 % 24); //时
            h = h < 10 ? '0' + h : h;
            var m = parseInt(times / 60 % 60); // 分
            m = m < 10 ? '0' + m : m;
            var s = parseInt(times % 60); // 当前的秒
            s = s < 10 ? '0' + s : s;
            return d + '天' + h + '时' + m + '分' + s + '秒';
        }
        console.log(countDown('2021-5-1 18:00:00'));
        var date = new Date();
        console.log(date);

3.数组对象

3.1检测是否为数组的两种方法
  • instanceof 运算符

    instance v. 举例 n.例子

    • instanceof 可以判断一个对象是否是某个构造函数的实例

      var arr = [1, 23];
      var obj = {
              
              };
      console.log(arr instanceof Array); // true
      console.log(obj instanceof Array); // false
      
  • Array.isArray()

    • Array.isArray()用于判断一个对象是否为数组,isArray() 是 HTML5 中提供的方法

      var arr = [1, 23];
      var obj = {
              
              };
      console.log(Array.isArray(arr));   // true
      console.log(Array.isArray(obj));   // false
      

      h5新增方法 ie9以上才支持

3.2添加、删除数组元素方法

1 .push(参数1):在数组末尾添加一个或者多个元素

​ push完毕之后返回新数组的长度

var arr = [1,2,3];
console.log(arr.push(4,'nihaoma'));

2 .unshift ( )

在数组前面添加元素,完毕后返回数组新长度。

console.log(arr.unshift(‘red’,223));

3.pop()删除数组最后一个元素

一次之能删除一个,不跟参数。

返回值为被删除的那个元素。

4.shift()

​ 删除数组第一个元素。

  var arr = new Array(4)
        arr[0] = "合肥"
        arr[1] = "上海"
        arr[2] = "广州"
        arr[3] = "天津"
        document.write("原有数组元素为:" + arr)
        document.write("<br />")
        document.write("删除数组中的第一个元素为:" + arr.pop())
        document.write("<br />")
        document.write("删除元素后的数组为:" + arr)
3.3数组排序

1.reverse()反转数组

            var arr = new Array(4)
                arr[0] = "合肥"
                arr[1] = "上海"
                arr[2] = "广州"
                arr[3] = "天津"
                document.write("原有数组元素为:" + arr)
                document.write("<br />")
                document.write("反转数组:" + arr.reverse())
                document.write("<br />")
                document.write("反转元素后的数组为:" + arr)

2.sort()数组排序

​ join() 方法用于把数组中的所有元素放入一个字符串。

var arrSimple=new Array(1,8,7,6,2,5);
        arrSimple.sort();
       // document.writeln(arrSimple.join());
       console.log(arrSimple.join())

语法:arrayObject.sort(sortby);

参数sortby 可选,用来规定排序的顺序,但必须是函数

如果要得到自己想要的结果,不管是升序还是降序,就需要提供比较函数了。该函数比较两个值的大小,然后返回一个用于说明这两个值的相对顺序的数字。

比较函数应该具有两个参数 a 和 b,其返回值如下:

若 a 小于 b,即 a - b 小于零,则返回一个小于零的值,数组将按照升序排列。

若 a 等于 b,则返回 0。

若 a 大于 b, 即 b - a 结果小于零,则返回一个小于零的值,数组将按照降序排列。

        var arr = [7, 3, 6, 1, 5, 12];
        console.log(arr.sort());//[1, 12, 3, 5, 6, 7]
        console.log(arr.sort(function (a, b) {
    
    
            return a - b;
        })); //[1, 3, 5, 6, 7, 12]
3.4数组索引方法

indexof

1 .找到返回在数组的索引号
2 .找不到就返回-1。
3 .如果有重复,只返回第一个找到的数组索引号

array.indexOf(item,start)

参数 描述
item 必须。查找的元素。
start 可选的整数参数。规定在数组中开始检索的位置。它的合法取值是 0 到 stringObject.length - 1。如省略该参数,则将从字符串的首字符开始检索。

start 从0开始计算。数组内容数字位置也是从0开始计算

案例:数组去重

遍历旧数组,然后去查询新数组,如果新数组中没有那就存入新数组。

调用indexof来判断元素是否存在。

function unique(arr) {
    
    
var newArr = [];
for (var i = 0;i<arr.length;i++)
{
    
    
	if(newArry.indexof(arr[i]) === -1) {
    
    
	newArry.push(arr[i]);
	}
}
return newArry;
}
3.5数组转字符串

1.toString

​ var arr = [1,2,3];

​ console.log(arr.toString());

2.join(分隔符)

​ var arr = [1,2,3];

​ console.log(arr1.join());//output 1,2,3

​ console.log(arr1.join(-));//output 1-2-3

​ console.log(arr1.join(&));//output 1&2&3

​ 可以自定义分隔符。

4.字符串对象

基本包装类型

​ 对象有属性和方法。复杂数据类型有属性与方法。对象是复杂数据类型的一种。

​ 基本包装类型,就是把简单数据类型,包装成复杂数据类型。

​ 把简单数据类型包装为复杂数据类型 加了new的就是复杂的。

​ 为了方便操作基本数据类型,JavaScript 还提供了三个特殊的引用类型:String、Number和 Boolean。

步骤1生成临时变量 把简单包装成复杂

​ var temp = new String(‘andy’);

步骤2 赋值给我们声明的字符变量

​ str = temp;

步骤3 销毁临时变量

​ temp = null;

字符串的不可变

​ 指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。

​ 当重新给字符串变量赋值的时候,变量之前保存的字符串不会被修改,依然在内存中重新给字符串赋值,会重新在内存中开辟空间,这个特点就是字符串的不可变。
​ 由于字符串的不可变,在大量拼接字符串的时候会有效率问题

根据字符返回位置

​ 字符串通过基本包装类型可以调用部分方法来操作字符串,indexOf(要查找的字符,开始查找的位置)

​ 案例:查找字符串"abcoefoxyozzopp"中所有o出现的位置以及次数

  1. 先查找第一个o出现的位置

  2. 然后 只要indexOf 返回的结果不是 -1 就继续往后查找

  3. 因为indexOf 只能查找到第一个,所以后面的查找,利用第二个参数,当前索引加1,从而继续查找

     var strNum = 'abbcopoiouothjkkk';
                var o = {
          
          };
    
                var index = strNum.indexOf('o');
                while (index !== -1){
          
          
                    console.log(index);
                    index = strNum.indexOf('o',index+1);
                    //每找到一次,就重新设定一次起始查找位置。
                }
    
根据位置返回字符

字符串通过基本包装类型可以调用部分方法来操作字符串,以下是根据位置返回指定位置上的字符:charAt(index),charCodeAt(index)

charAt 根据位置返回字符

str.charAt(3);

遍历所有字符,可以用charAt

for (var i = 0;i<str.length;i++){
    
    
console.log(str.charAt(i));
}

​ 在上述方法中,charCodeAt方法返回的是指定位置上字符对应的ASCII码.

案例:判断一个字符串 ‘abcoefoxyozzopp’ 中出现次数最多的字符,并统计其次数

  1. 核心算法:利用 charAt() 遍历这个字符串

  2. 把每个字符都存储给对象, 如果对象没有该属性,就为1,如果存在了就 +1

  3. 遍历对象,得到最大值和该字符

    ​注意:在遍历的过程中,把字符串中的每个字符作为对象的属性存储在对象总,对应的属性值是该字符出现的次数

            var strNum = 'abbcopoiouothjkkk';
            var o = {
    
    };

            for (var i = 0;i < strNum.length;i++){
    
    
                var chars = strNum.charAt(i);
                if (o[chars]) {
    
     //相当于把 chars 当作了对象O的一个属性
                    o[chars]++;
                } else {
    
    
                    o[chars] = 1;
                }
            }

            console.log(o);

            var max = 0;
            var ch  = '';
            for (var k in o) {
    
    
                if (o[k] > max){
    
    
                    max = o[k];
                    ch = k;
                }
            }

            console.log(max) 
            console.log(ch);

字符串操作方法

​ 字符串通过基本包装类型可以调用部分方法来操作字符串

concat()

拼接字符串

replace()方法

​ replace() 方法用于在字符串中用一些字符替换另一些字符,其使用格式如下:

字符串.replace(被替换的字符串, 要替换为的字符串);
          while (strNum.indexOf('o') !== -1) {
    
    
                strNum = strNum.replace('o','*');
            }
            console.log(strNum);

split()方法

​ split()方法用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。

​ 其使用格式如下:

字符串.split("分割字符")

简单数据类型与复杂数据类型

2.1 简单数据类型

简单类型基本数据类型值类型):在存储时变量中存储的是值本身,包括string ,number,boolean,undefined,null。

null 返回的是一个空对象,不是null。

var timer = null
console.log(typeof(timer))
结果为: “object”

2.2 复杂数据类型

复杂数据类型(引用类型):在存储时变量中存储的仅仅是地址(引用),通过 new 关键字创建的对象(系统对象、自定义对象),如 Object、Array、Date等;

2.3 堆栈

js没有堆和栈

  • 堆栈空间分配区别:

1、栈(操作系统):由操作系统自动分配释放存放函数的参数值、局部变量的值等。其操作方式类似于数据结构中的栈;

简单数据类型存放到栈里面

2、堆(操作系统):存储复杂类型(对象),一般由程序员分配释放,若程序员不释放,由垃圾回收机制回收。

  • 简单数据类型的存储方式

    ​ 值类型变量的数据直接存放在变量(栈空间)中。

  • 复杂数据类型的存储方式

    ​ 引用类型变量(栈空间)里存放的是地址,真正的对象实例存放在堆空间中。

2.4 简单类型传参

​ 函数的形参也可以看做是一个变量,当我们把一个值类型变量作为参数传给函数的形参时,其实是把变量在栈空间里的值复制了一份给形参,那么在方法内部对形参做任何修改,都不会影响到的外部变量。

function fn(a) {
    
    
    a++;
    console.log(a); 
}
var x = 10;
fn(x); 
console.log(x); 
// result 11
// result  10

2.5 复杂数据类型传参

​ 函数的形参也可以看做是一个变量,当我们把引用类型变量传给形参时,其实是把变量在栈空间里保存的堆地址复制给了形参,形参和实参其实保存的是同一个堆地址,所以操作的是同一个对象。

function Person(name) {
    
    
    this.name = name;
}
function f1(x) {
    
     // x = p
    console.log(x.name); // 2. 这个输出什么 ?    
    x.name = "张学友";
    console.log(x.name); // 3. 这个输出什么 ?    
}
var p = new Person("刘德华");
console.log(p.name);    // 1. 这个输出什么 ?   
f1(p);
console.log(p.name);    // 4. 这个输出什么 ?  

猜你喜欢

转载自blog.csdn.net/codemokey/article/details/114199395