Loading

JavaScript详解(一)

回顾

前端三要素

  • HTML(结构):超文本标记语言(Hyper Text Markup Language)决定网页结构和内容
  • CSS(表现):层叠样式表(Cascading Style Sheets),设定网页的表现形式
  • JavaScript(行为):是一种弱类型脚本类型语言,其源代码不需要经过编译,而是由浏览器解释运行,用于控制网页的行为

表现层(CSS)

CSS层叠样式表是一门标记语言,并不是编程语言,因此不可以自定义变量,不可以引用等,换句话说就说不具备任何语法支持,它主要缺陷如下:

  • 语法不够强大,比如无法嵌套书写,导致模块化开发中需要书写很多重复的选择器;
  • 没有变量和合理的样式复用机制,使得逻辑上相关的属性值必须以字面量的形式重复输出,导致难以维护;

这就导致了我们在工作中无端增加了许多工作量。为了解决这个问题,前端开发人员会使用一种称之为CSS预处理器的工具,提供CSS缺失的样式层复用机制、减少代码冗余,提高样式代码的可维护性,大大提高了前端在样式上的开发效率。

什么是CSS预处理器

CSS预处理器定义了一种新的语言,其基本思想是,用一种专门的编程语言,为CSS增加了一些编程的特性,将CSS作为目标生成文件,然后开发者就只要使用这种语言进行CSS的编码工作。转化成通熟易懂的话就是“用一种专门的编程语言,进行Web页面样式设计,再通过编译器转化成正常的CSS文件,以供项目使用。

行为层(JavaScript)

JavaScript 一门弱类型脚本语言,其源代码在发往客户端运行之前不需经过编译,而是将文本格式的字符代码发送给浏览器由浏览器解释运行。

Native 原生JS开发

原生JS开发,也就是让我们按照【ECMAScript】标准的开发方式,简称是ES,特点是所有浏览器都支持。截止到当前博客发布时间,ES标准已发布如下版本:

  • ES3
  • ES4(内部。未正式发布)
  • ES5(全浏览器支持)
  • ES6(常用,当前主流版本:webpack打包成为ES5支持!)

JavaScript框架

  • jQuery:大家熟知的JavaScript框架,优点是简化了DOM操作,缺点是DOM操作太频繁,影响前端性能;在前端眼里使用它仅仅是为了兼容IE6、7、8
  • Angular: Google收购的前端框架,由一群Java程序员开发,其特点是将后台的MVC模式搬到了前端并增加了模块化开发的理念,与微软合作,采用TypeScript语法开发;对后台程序员友好,对前端程序员不太友好;最大的缺点是版本迭代不合理(如:1代 > 2代,除了名字,基本就是两个东西;截止发表博客时已推出了 Angular6)
  • React:Facebook 出品,一款高性能的JS前端框架;特点是提出了新概念【虚拟DOM】用于减少DOM操作,在内存中模拟DOM操作,有效的提升了前端渲染效率;缺点是使用复杂,因为需要学习一门【JSX】语言
  • Vue:一款渐进式JavaSript框架,所谓渐进式就是逐步实现新特性的意思,如实现模块化开发、路由、状态等新特性。其特点是综合了Angular(模块化)和React(虚拟DOM)的优点
  • Axios:前端通信框架;因为Vue的边界很明确,就是为了处理DOM,所以并不具备通信能力,此时就需要额外使用一个通信框架与服务器交互;当然也可以直接选择使用jQuery提供的AJAX通信功能

UI框架

  • Ant-Design: 阿里巴巴出品,基于React的UI框架
  • ElementUI、iview、ice:饿了么出品,基于Vue的UI框架
  • Bootstrap:Twitter退出的一个用于前端开发的开源工具包
  • AmazeUI:又叫“妹子UI”,一款HTML5跨屏前端框架

JavaScript构建工具

  • Babel:JS编译工具,主要用于浏览器不支持的ES新特性,比如用于编译TypeScript
  • WebPack:模块打包器,主要作用是打包、压缩、合并及按序加载

JavaScript入门

什么是JavaScript

JavaScript是一门世界上最流行的脚本语言

一个合格的后端人员,必须要精通JavaScript

ECMAScript它可以理解为是JavaScript的一个标准

最新版本已经到es6

但是大部分浏览器还只停留在支持 es5 代码上

基本使用

  • 内部标签使用
<script>
    //......
</script>
  • 外部引入
    abc.js
alert("hello,world!")

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--外部引入-->
    <!--注意:script标签,必须成对出现-->
    <script src="./js/qj.js"></script>
</head>
<body>

</body>
</html>

基本语法入门

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <!--javascript 严格区分大小写-->
    <script>
        // 1、定义变量  变量类型 变量名 = 变量值;
        var score = 71;
        alert(score);
        // 2、条件控制
        if (score>60 && score<70){
            alert("60~70");
        }else if(score>70 && score<80){
            alert("70~80");
        }else {
            alert("other")
        }

        // console.log(score); 在浏览器的控制台打印变量
    </script>
</head>
<body>

</body>
</html>

浏览器控制台常用语法

# 弹窗
alert(score);

# 打印日志
console.log(score);

数据类型

数值,文本,图形,音频,视频......

变量

var 王者荣耀 = "王者荣耀";

number

js不区分小数和整数,Number

123  // 整数123
123.1  // 浮点数123.1
1.123e3  // 科学计数法
-99  // 负数
NaN  // not a number
Infinity // 表示无限大

字符串

‘abc’ "abc"

布尔值
true,false

逻辑运算

&&  两个都为真,结果为真

||  一个为真,结果为真

!  真即假,假即真

比较运算符

=
== 等于(类型不一样,值一样,也会判断为true)
=== 绝对等于(类型一样,值一样,结果为true)

⚠️注:这是JS的一个缺陷,坚持不使用==

须知

  • NaN==NaN,这个与所有的数值都不相等,包括自己
  • 只能通过isNaN(NaN)来判断这个数值是否是NaN
console.log((1/3) === (1-2/3))
console.log(Math.abs((1/3)-(1-2/3))<0.00000001)
false
true

尽量避免使用浮点数进行运算,存在精度问题!

null和undefined

  • null 空
  • undefined 未定义

数组
java的数值必须是相同类型的对象,js中不需要这样

// 保证代码的可读性,尽量使用 []
var arr = [1,2,3,4,5,'hello',true];
new Array(1,12,3,4,5,'hello');

取数组下标:如果越界了,就会undefined

undefined

对象
对象是大括号,数组是中括号

每个属性之间使用逗号隔开,最后一个不需要添加

// Person person new Person(1,2,3,4,5);
var person = {
    name: "binzaza",
    age: 3,
    tags: ['js','java','web','...']
}

取对象的值

person.name
> binzaza
person.age
> 3

严格检查模式

        // 全局变量
        i= 1;
        //严格检查模式,预防javascript的随意性导致产生的一些问题

        // 局部变量建议都使用 let 去定义~
        'use strict';
        let j = 3;

字符串类型详解

  1. 正常字符串我们使用单引号,或者双引号包裹
  2. 注意转译字符
\'
\n
\t
\u4e2d    \u#### unicode字符

\x41   Ascll字符
  1. 多行字符串编写
        //tab 上面 esc下面
        let msg =
            `hello
            world
            你好ya
            你好`
        console.log(msg);
hello
world
你好ya
你好
  1. 模板字符串
        let name = "binzaza";
        let age = 3;
        let message = `你好呀,${name}`+`你今年${age}岁`;
        console.log(message);
你好呀,binzaza你今年3岁
  1. 字符串长度
str.length
  1. 字符串的可变性,不可变
var student = "student";
student[0]=1;

Uncaught TypeError
7. 大小写转换

        let student = "sTuDent";

        // 注意,这里是方法,不是属性
        console.log(student.toUpperCase());
        console.log(student.toLowerCase());
STUDENT
student
  1. 获取字符串下标
        let student = "sTudent001";
        console.log(student.indexOf("d"))
3
  1. 截取字符串
        let student = "sTudent001";
        // 从第一个字符串截取到最后一个字符串
        console.log(student.substring(1));
        console.log(student.substring(1,3));
Tudent001
Tu

数组类型详解

Array可以包含任意的数据类型

var arr = [1,2,3,4,5] //通过下标取值和赋值
arr[0]
arr[0] = 1
  1. 长度
arr.length

注意:假如给arr.length赋值,数组就会发生变化~,如果赋值过小,元素就会丢失
2. 通过元素获得下标索引

arr.indexof(2)
1

字符串的“1”和数字1是不同的

  1. slice()截取Array的一部分,返回一个新数组
arr = [1,2,3,4,5,6,"1","2"]
arr.slice(3)
> (5) [4,5,6,"1","2"]

arr.slice(1,5)
> (4) [2,3,4,5]

类似于String中的substring
4. 尾部push、pop

// push: 压入到尾部
arr = [1,2,3,4,5,6,"1","2"]
arr.push("a","b");
> (9) [1, 2, 3, 4, 5, '1', '2', 'a', 'b']

// pop: 弹出尾部的一个元素
arr.pop()
> 'b'

arr.pop()
> 'a'
  1. 头部unshift(),shift()
// unshift头部添加元素
arr.unshift("a","b");
> (9) ['a', 'b', 1, 2, 3, 4, 5, '1', '2'];

// shift 弹出头部一个元素
arr.shift();
> 'a'
  1. 排序sort()
arr.sort()
> (7) [1, '1', 2, '2', 3, 4, 5]
  1. 元素反转reverse()
arr = ["A","B","C"];
arr.reverse();
> (3) ['C', 'B', 'A']
  1. 拼接concat()
arr = ["A","B","C"];
arr.concat([1,2,3])
> (6) ['A', 'B', 'C', 1, 2, 3]

arr;
> (3) ['A', 'B', 'C']

注意:concat() 并没有修改数组,只是会返回一个新的数组
9. 连接符join

arr = ["A","B","C"];
arr.join('-');
> 'A-B-C'
  1. 多维数组
arr = [[1,2],[3,4],[5,6]];
arr[1][1];
> 4

数组:存储数据,方法可以自己实现

对象

若干个键值对

var = 对象名 = {
    属性名: 属性值,
    属性名: 属性值,
    属性名: 属性值
}

// 定义了一个person对象,它有4个属性
        var person = {
            name: "binzaza",
            age: 3,
            email: "binzichen@126.com",
            score: 0
        }

js中的对象,键值队描述属性 xxx:xxx, 多个属性用逗号隔开,最后一个属性不加逗号!

  1. 对象赋值
person.name = "xiaoming";
> "xiaoming"

person.name;
> "xiaoming"
  1. 使用一个不存在的对象属性,不会报错!
person.haha
> undefined
  1. 动态的删减属性
delete person.name;
> true

person;
> {age: 3, email: 'binzichen@126.com', score: 0}
  1. 动态的添加,直接给新的属性添加值即可
person.haha = "haha";
> "haha"

person;
> {age: 3, email: 'binzichen@126.com', score: 0, haha: 'haha'}
  1. 判断属性值是否存在这个对象中! xxx in xxx!
'age' in person;
> true

// 继承
'toString' in person;
> true
  1. 判断一个属性是否是这个对象自身拥有的 hasOwnProperty()
person.hasOwnProperty('toString');
> false

person.hasOwnProperty('age');
> true

流程控制

  1. if 判断
        let age = 3;
        
        if (age>3){
            alert("haha");
        } else {
            alert("kuwa~")
        }
  1. while 循环
        let age = 3;
        
        while (age<100){
            age = age +1;
            console.log(age)
        }
  1. for 循环
        for (let i = 0; i < 100; i++){
            console.log(i)
        }
  1. forEach 循环
var age = [12,3,12,3,12,3,12,31,23,123];

// 函数
age.forEach(function (value){
    console.log(value)
})

Map和Set

ES6新特性

map

        // 学生成绩,学生的名字
        // var names = ["tom","jack","haha"];
        // var scores = [100,80,90];

        var map = new Map([["tom",100],["jack",80],["haha",90]]);
        var score = map.get("tom"); // 通过key获得value
        console.log(score);

        map.set("admin",70);
        var score2 = map.get("admin");
        console.log(score2)
> 100
> 70

set: 无序不重复的集合

        var set = new Set([3,1,3,3,7,"a"]);
        set.add(5);
        set.delete(3);
        console.log(set);

iterator迭代

使用iterator来遍历迭代我们的map、set

遍历数组

        var arr = [3,4,5];
        for (var x of arr){
            console.log(x)
        }

遍历map

        var map = new Map([["tom",100],["jack",80],["haha",90]]);
        for (let x of map){
            console.log(x)
        }

遍历set

        var set = new Set([4,5,6,7]);
        for (let x of set){
            console.log(x)
        }

函数

定义函数

定义方式一

function abs(x){
    if (x>=0){
        return x;
    }else{
        return -x;
    }
}
abs(-10);
> 10

abs(20);
> 20

一旦执行了return,代表函数结束,返回结果!

如果没有执行return,函数执行完也会返回结果,结果就是undefined

定义方式二

        var abs = function(x){
            if(x>=0){
                return x;
            }else{
                return -x;
            }
        }
abs(-30);
> 30

abs(40);
> 40

function(x){ ... } 这是一个匿名函数。但是可以把结果赋值给abs,通过abs就可以调用函数!

调用函数

abs(10)  // 10
abs(-10)  // 10

参数问题

javaScript可以传任意个参数,也可以不传参数

参数进来是否存在的问题,假设不存在参数怎么做

        var abs = function(x){
            if (typeof x!== "number"){
                throw 'Not a Number';
            }
            if(x>=0){
                return x;
            }else{
                return -x;
            }
        }

arguments

arguments 是一个js免费赠送的关键字
代表,传递进来的所有参数,是一个数组

        var abs = function(x){
            console.log('x=>'+x);
            for (var i = 0; i<arguments.length;i++){
                console.log(arguments[i]);
            }
            if(x>=0){
                return x;
            }else{
                return -x;
            }
        }

问题:arguments包含所有的参数,我们有时候想使用多余的参数来进行附加操作,需要排除已有的参数

rest

以前

        function aaa(a,b){
            console.log("a=>"+a);
            console.log("b=>"+b);
            if (arguments.length>2){
                for (var i=2;i<arguments.length;i++){
                    // ...
                }
            }
        }

ES6引入的新特性,获取除了已经定义的参数之外所有参数

        function aaa(a,b,...rest){
            console.log("a=>"+a);
            console.log("b=>"+b);
            console.log(rest);
        }
aaa(5,6,7,8,9);
> a=>5
> b=>6
> (3) [7, 8, 9]

变量的作用域

在javascript中,var定义的变量实际是有作用域的

假设在函数体中声明,则在函数体外不可以使用~ (闭包

function qj(){
    var x = 1;
    x = x + 1;
}

x = x + 2; // Uncaught ReferenceError: x is not defined

如果两个函数使用了相同的变量名,只要在函数内部,就不冲突

funtction qj(){
    var x = 1;
    x = x + 1;
}

function qj2(){
    var x = 'A';
    x = x + 1;
}

内部函数可以访问内部函数的成员,反之则不行

        function qj(){
            var x = 1;

            // 内部函数可以访问内部函数的成员,反之则不行
            function qj2(){
                var y = x + 1;
            }

            var z = y + 1; // Uncaught ReferenceError: y is not defined
        }

假设,内部函数变量和外部函数变量重名,则用内部变量

        function qj(){
            var x = 1;
            
            function qj2(){
                var x = 'A';
                console.log('inner'+x); // innerA
            }
            console.log('outer'+x); // outer1
            qj2()
        }
        qj()

函数查找变量从自身函数开始,由内向外查找

提升变量的作用域

function qj(){
    var x = "x" + y;
    console.log(x);
    var y = 'y';
}
// 结果
> xundefined

说明,js执行引擎,自动提升了y的声明,但是不会提升y的值

function qj2(){
    var y;
    
    var x = 'x' + y;
    console.log(x);
    y = 'y';
}

这个是在javascript建立之初就存在的特性,养成规范,所有的变量定义都放在函数的头部,不要乱放,便于代码维护。

function qj2(){
    var x = 1,
        y = x + 1,
        z,i; //undefined
    
    // 之后随意用
}

全局函数

//全局变量
x = 1;

function f(){
    console.log(x);
}
f();
console.log(x);

全局对象 window

var x = 'xxx';
alert(x);
alert(window.x); // 默认所有的全局变量,都会绑定在window对象下

alert()函数本身也是一个window变量

        var x = 'xxx';

        window.alert(x);

        var old_alert = window.alert;

        window.alert = function (){};

        // 发现 alert() 失效了
        window.alert(123);

        // 恢复
        window.alert = old_alert;
        window.alert(456);

javascript 实际上只有一个全局作用域,任何变量(函数也可以视为变量),假设没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,报错RefrenceError

规范

由于我们所有的全局变量都会绑定在我们的window上。如果不同的js文件,使用了相同的全局变量,冲突 -> 如何能减少冲突

        // 唯一全局变量
        var MyAPP = {};

        // 定义全局变量
        MyAPP.name = "binzaza";
        MyAPP.add = function (a,b) {
            return a+b;
        }

把自己的代码全部放入自己定义的唯一空间名字中,降低全局命名冲突的问题~

局部作用域let

        function aaa(){
            for (var i = 0; i < 100; i++) {
                console.log(i)
            }
            console.log(i+1); // 问题 -> i出了这个作用域还可以使用
        }

ES6 let关键字,解决了局部作用域冲突问题

        function aaa(){
            for (let i = 0; i < 100; i++) {
                console.log(i)
            }
            console.log(i+1); // Uncaught ReferenceError: i is not defined
        }

建议大家使用let去定义局部作用域的变量;

常量 const

在ES6之前,怎么定义常量:只用全部大写字母命名的就是常量;建议不要修改这样的值

        var PI = '3.1415';

        console.log(PI);

        PI = '926.54';
        console.log(PI);

在ES6引入了常量关键字 const

        const PI = '3.1415'; // 只读变量
        console.log(PI);

方法

方法就是把函数放在对象的里面,对象只有两个东西:属性和方法

        var binzaza = {
            name: "bin",
            birth: 2002,
            // 方法
            age: function (){
                // 今年 - 出生年
                var now = new Date().getFullYear();
                return now - this.birth;
            }
        }
// 调用方法
binzaza.age();
> 20

this.代表什么

        function getAge(){
                // 今年 - 出生年
                var now = new Date().getFullYear();
                return now - this.birth;
        }

        var binzaza = {
            name: "bin",
            birth: 2002,
            // 方法
            age: getAge
        }

this是无法指向的,是默认指向调用它的那个对象

apply

在js中可以控制this指向

        function getAge(){
                // 今年 - 出生年
                var now = new Date().getFullYear();
                return now - this.birth;
        }

        var binzaza = {
            name: "bin",
            birth: 2002,
            age: getAge
        };

        getAge.apply(binzaza,[]);
> 20

js中可以控制this指向

        function getAge(){
                // 今年 - 出生年
                var now = new Date().getFullYear();
                return now - this.birth;
        }

        var binzaza = {
            name: "bin",
            birth: 2002,
            age: getAge
        };

        var xiaoming = {
            name: "小明",
            birth: 2008,
            age: getAge
        };

        getAge.apply(xiaoming,[]);
> 14

内部对象

标准对象

typeof 123
> 'number'
typeof '123';
> 'string'
typeof true;
> 'boolean'
typeof NaN;
> 'number'
typeof [];
> 'object'
typeof {};
> 'object'
typeof Math.abs;
> 'function'
typeof undefined;
> 'undefined'

Date

基本使用

    var now = new Date();

    now.getFullYear(); // 年
    now.getMonth();  // 月 0~11 代表月
    now.getDate();  // 天
    now.getDay();  // 星期
    now.getHours(); // 时
    now.getMinutes(); // 分
    now.getSeconds(); // 秒
    now.getTime();  // 时间戳 全世界统一

转换

console.log(new Date(1661144775292));
> Mon Aug 22 2022 13:06:15 GMT+0800 (中国标准时间)
now.toLocaleString();
> '2022/8/22 13:06:15'
now.toGMTString();
> 'Mon, 22 Aug 2022 05:06:15 GMT'

Json

json是什么

早期,所有数据传输习惯使用xml

  • json是一种轻量级的数据交换格式
  • 简洁和清晰的层次结构使得JSON 成为理想的数据交换语言
  • 易于阅读和编写,同时也易于机器解析和生成,并有效地提升网络的传输效率

在JavaScript中一切皆为对象,任何js支持的类型都可以用json来表示

格式

  • 对象都用 {}
  • 数组都用 []
  • 所有的键值对 都是用key:value
    var user = {
        name: "binzaza",
        age: 3,
        sex: "男"
    }

    // 对象转化为json字符串 {"name":"binzaza","age":3,"sex":"男"}
    var jsonUser = JSON.stringify(user);

    // json字符串转化为对象
    var obj = JSON.parse('{"name":"binzaza","age":3,"sex":"男"}')
posted @ 2022-09-04 00:01  Binzichen  阅读(32)  评论(0编辑  收藏  举报