前端基础——JavaScript(基础语法)(下篇)

目录

数组

创建数组

获取数组元素

新增数组元素

1.通过修改length新增

2.通过下标新增

3.使用push进行追加元素

[代码示例: 给定一个数组, 把数组中的奇数放到一个 newArr 中.](#代码示例: 给定一个数组, 把数组中的奇数放到一个 newArr 中.)

删除数组中的元素

函数

语法格式

关于参数个数

1) 如果实参个数比形参个数多, 则多出的参数不参与函数运算 如果实参个数比形参个数多, 则多出的参数不参与函数运算)

2) 如果实参个数比形参个数少, 则此时多出来的形参值为 undefined 如果实参个数比形参个数少, 则此时多出来的形参值为 undefined)

函数表达式

作用域

作用域链

对象

基本概念

1.使用字面量创建对象常用

使用对象的属性和方法:

[2.使用new Object创建对象](#2.使用new Object创建对象)

3.使用构造函数创建对象

基本语法

理解new关键字

JavaScript的对象和Java对象的区别

1.JavaScript没有"类"的概念

2.JavaScript对象不区分"属性"和"方法"

3.JavaScript对象没有private/public等访问控制机制

4.JavaScript对象没有继承

5.JavaScript没有"多态"

class&构造方法

[static 关键字](#static 关键字)

继承(了解)


书接上文:前端基础------JavaScript(基础语法)(上篇)~~

数组

JavaScript 中的数组和 Java 中的数组还是有一定差异的~~

创建数组

闲聊:回忆一下在 Java 中数组的创建方式~~

int\[\] array={1,2,3};

int\[\] array=new int3;

int\[\] array=new int\[\]{1,2,3};

使用 new 关键字创建

javascript 复制代码
// Array 的 A 要大写
var arr = new Array();

使用字面量方式创建 常用

javascript 复制代码
var arr = [];
var arr2 = [1, 2, 'haha', false]; // 数组中保存的内容称为 "元素"

注意 : JS 的数组不要求元素是相同类型.

这一点和 C, C++, Java 等静态类型的语言差别很大. 但是 Python, PHP 等动态类型语言也是如此

获取数组元素

使用下标的方式访问数组元素(从 0 开始)(和 Java 一样~~)

javascript 复制代码
var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
console.log(arr);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
arr[2] = '小猫凯迪';
console.log(arr);

代码展示👇

javascript 复制代码
        let array=new Array();
        let array1=[1,2,3,"4"]
        console.log(array1)

效果展示👇

如果下标超出范围读取元素, 则结果为 undefined

javascript 复制代码
console.log(arr[3]);   // undefined
console.log(arr[-1]);  // undefined

注意 : 不要给数组名直接赋值, 此时数组中的所有元素都没了

相当于本来 arr 是一个数组, 重新赋值后变成字符串了

javascript 复制代码
var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
arr = '小猫凯迪';

代码展示👇

javascript 复制代码
        let array=new Array();
        let array1=[1,2,3,"4"]
        console.log(typeof(array1))
        console.log(array1)
        console.log(array1[2])
        //这个代码放到 Java 中,会抛出一个数组越界的异常,但是在这里却是 undefined
        console.log(array1[10])
        console.log(array1[-10])
        array1="小比特"
        console.log(typeof(array1))
        console.log(array1)

效果展示👇

新增数组元素

在 Java 中我们需要先将数组转换成 List,再 add 去添加,然后再转换回数组,但是在 JavaScript 就没有这么麻烦了~~

1.通过修改length新增

相当于在末尾新增元素. 新增的元素默认值为 undefined

javascript 复制代码
var arr = [9, 5, 2, 7];
arr.length = 6;
console.log(arr);
console.log(arr[4], arr[5]);

代码展示👇

javascript 复制代码
        let array=[1,2,3,4]
        array.length = 10;
        console.log(array)
        array[7] = 8
        console.log(array)
        console.log(array[9])

效果展示👇

2.通过下标新增

如果下标超出范围赋值元素, 则会给指定位置插入新元素

javascript 复制代码
var arr = [];arr[2] = 10;console.log(arr)

此时这个数组的 01 都是 undefined

代码展示👇

javascript 复制代码
    let array = new Array()
    console.log(array)
    for(i=0;i<10;i++)
        array[i]=i;
    array[20] = 20
    console.log(array)

效果展示👇

3.使用push进行追加元素
代码示例 **:**给定一个数组, 把数组中的奇数放到一个 newArr 中.
javascript 复制代码
var arr = [9, 5, 2, 7, 3, 6, 8];
var newArr = [];
for (var i = 0; i < arr.length; i++) {
    if (arr[i] % 2 != 0) {
        newArr.push(arr[i]);
   }
}
console.log(newArr);

效果展示👇

删除数组中的元素

使用 splice 方法删除元素

javascript 复制代码
var arr = [9, 5, 2, 7];
// 第一个参数表示从下表为 2 的位置开始删除. 第二个参数表示要删除的元素个数是 1 个
arr.splice(2, 1);
console.log(arr);
// 结果
[9, 5, 7]

效果展示👇

目前咱们已经用到了数组中的一些属性和方法.

arr.length, length 使用的时候不带括号, 此时 length 就是一个普通的变量(称为成员变量, 也叫属性)

arr.push(), arr.splice() 使用的时候带括号, 并且可以传参数, 此时是一个函数 (也叫做方法)

函数

语法格式

javascript 复制代码
// 创建函数/函数声明/函数定义
function 函数名(形参列表) {
    函数体
    return 返回值;
}
// 函数调用
函数名(实参列表)           // 不考虑返回值
返回值 = 函数名(实参列表)   // 考虑返回值

函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次关于参数个数

javascript 复制代码
//定义没有参数列表,也没有返回值的一个函数
function hello() {
    console.log("hello");
}
// 如果不调用函数, 则没有执行打印语句
hello();

效果展示👇

代码展示👇

javascript 复制代码
    //定义一个有参数,没有返回值的一个函数
    function HelloXiaobite(num,name){
        console.log(num + "Hello" + name)
    }
    HelloXiaobite(1,"CoderYanger")

效果展示👇

代码展示👇

javascript 复制代码
    function hello() {
        console.log("hello");
    }
    //定义一个有参数,有返回值的一个函数
    function HelloXiaobite(num,name){
        console.log(num + "Hello" + name)
        return 1;
    }
    let b = hello();
    console.log(typeof(b))
    let a = HelloXiaobite(1,"CoderYanger")
    console.log(typeof(a))

效果展示👇

函数的返回值类型就是 return 的类型,这也恰好验证了 JavaScript 是一个动态语言的这个特性了~~

调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.

函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)

javascript 复制代码
// 调用函数
hello();
// 定义函数
function hello() {
    console.log("hello");
}

关于参数个数

实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配

1) 如果实参个数比形参个数多, 则多出的参数不参与函数运算
javascript 复制代码
sum(10, 20, 30);    // 30

代码展示👇

javascript 复制代码
    //定义一个有参数,有返回值的一个函数
    function HelloXiaobite(num,name){
        console.log(num + ",Hello," + name)
        return 1;
    }
    //实参个数比形参个数多
    HelloXiaobite(1,"CoderYanger",3)

效果展示👇

2) 如果实参个数比形参个数少, 则此时多出来的形参值为 undefined
javascript 复制代码
sum(10);    // NaN, 相当于 num2 为 undefined.

代码展示👇

javascript 复制代码
    //定义一个有参数,有返回值的一个函数
    function HelloXiaobite(num,name){
        console.log(num + ",Hello," + name)
        return 1;
    }
    //实参个数比形参个数少
    HelloXiaobite();

效果展示👇

JS 的函数传参比较灵活, 这一点和其他语言差别较大. 事实上这种灵活性往往不是好事

函数表达式

代码展示👇

javascript 复制代码
    function HelloXiaobite(num,name){
        console.log(num + ",Hello," + name)
        return 1;
    }
    let result = function Sum(){
        //计算1~100之间的和
        ret=0;
        for(i=0;i<=100;i++)
            ret+=i
        return ret
    }
    console.log(result())

效果展示👇

另外一种函数的定义方式

javascript 复制代码
var add = function() {
 var sum = 0;
    for (var i = 0; i < arguments.length; i++) {
        sum += arguments[i];
   }
    return sum;
}
console.log(add(10, 20));            // 30
console.log(add(1, 2, 3, 4));        // 10
console.log(typeof add);             // function

此时形如 function() { } 这样的写法定义了一个匿名函数, 然后将这个匿名函数用一个变量来表示.

后面就可以通过这个 add 变量来调用函数了.

代码展示👇

javascript 复制代码
    let b = function(){
        //通过 arguments 可以打印调用参数列表
        console.log(arguments)
    }
    b();
    b(1,2,3)

效果展示👇

可见传参数之前长度是 0,传参数之后长度就变成 3 了

JS 中函数是一等公民, 可以用变量保存, 也可以作为其他函数的参数或者返回值

作用域

某个标识符名字在代码中的有效范围.

在 ES6 标准之前, 作用域主要分成两个

全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.

局部作用域/函数作用域: 在函数内部生效,这一点和 Java 还是非常大的~~

javascript 复制代码
// 全局变量
let num = 10;
console.log(num);
function test() {
    // 局部变量
   let num = 20;
    console.log(num);
}
function test2() {
    // 局部变量
    let num = 30;
    console.log(num);
}
test();
test2();
console.log(num);
// 执行结果
10
20
30
10

以上这种写法在 Java 中是不支持的,但是在 JavaScript 中就可以支持,效果展示👇

类似的,下面这段代码在 Java 中同样不支持,但是在 JavaScript 中却可以正常运行,代码展示👇

javascript 复制代码
    for(i = 1;i <= 100; i++){

    }
    console.log(i)

效果展示👇

创建变量时如果不写 var、let, 此时这个变量就是一个全局变量

代码展示👇

javascript 复制代码
    for(let i = 1;i <= 100; i++){

    }
    console.log(i)

效果展示👇

另外, 很多语言的局部变量作用域是按照代码块(大括号)来划分的, JS 在 ES6 之前不是这样的

javascript 复制代码
if (1 < 2) {
 var a = 10;
}
console.log(a);

作用域链

背景:

函数可以定义在函数内部

内层函数可以访问外层函数的局部变量.

内部函数可以访问外部函数的变量. 采取的是链式查找的方式. 从内到外依次进行查找

javascript 复制代码
    let num=10
    function test01(){
        let num=100
        //100
        console.log(num)
        function test02(){
            let num=200
            //200
            console.log(num)
        }
        test02()
    }
    test01()

效果展示👇

如果我们把 test02() 中的 num 注释掉之后,num 会从内往外找,结果找到 test01() 中的 num ,值为 100,代码展示👇

javascript 复制代码
    let num=10
    function test01(){
        let num=100
        //100
        console.log(num)
        function test02(){
            //let num=200
            //200
            //此时找到上面的 num,值为 100
            console.log(num)
        }
        test02()
    }
    test01()

效果展示👇

执行 console.log(num) 的时候, 会现在 test2 的局部作用域中查找 num. 如果没找到, 则继续去 test1 中查找. 如果还没找到, 就去全局作用域查找

类似的,如果我们把 test01() 中的 num 也注释掉,那么它在找的时候就会找到 全局变量的 num,值为 10,代码展示👇

javascript 复制代码
    let num=10
    function test01(){
        //let num=100
        //100
        //此时找到的是上面的全局变量 10
        console.log(num)
        function test02(){
            console.log(num)
        }
        test02()
    }
    test01()

效果展示👇

那么如果我们把全局变量的 num 也注释掉呢??直接给出效果展示👇

我们发现实在找不到的时候给出的提示是未定义~~

总的来说,作用域链就相当于在函数体内部去调用一个变量的时候,首先在我们自己的函数体内部去找,如果找到了,直接使用,没找到,就从我们这个函数的上一层函数里面去找我们的变量,还没找到,就从上上一层去找,直到找到全局变量为止,如果全局变量还没有,就会报错了~~

对象

有了 Java 的基础,我们理解"对象"就非常轻松了~~

基本概念

对象是指一个具体的事物

"电脑" 不是对象, 而是一个泛指的类别. 而 "我的联想笔记本" 就是一个对象

在 JS 中, 字符串, 数值, 数组, 函数都是对象
每个对象中包含若干的属性和方法.

属性: 事物的特征.

方法: 事物的行为.

例如, 你有一个女票.

她的身高体重三围这些都是属性.

她的唱歌, 跳舞, 暖床都是方法
对象需要保存的属性有多个, 虽然数组也能用于保存多个数据, 但是不够好.

例如表示一个学生信息. (姓名蔡徐坤, 身高 175cm, 体重 170斤)

var student = '蔡徐坤', 175, 170;

但是这种情况下到底 175 和 170 谁表示身高, 谁表示体重, 就容易分不清

JavaScript 的对象 和 Java 的对象概念上基本一致. 只是具体的语法表项形式差别较大

1.使用字面量创建对象常用

使用 { } 创建对象

javascript 复制代码
    let a = {}; // 创建了一个空的对象,只不过它没有属性和方法
    let student = {
        name: 'CoderYanger',
        height: 180,
        weight: 120,
        sayHello: function() {
        console.log("hello");
    }
    };
    //此时这个 student 就有了它的属性和方法
    console.log(student.name)//第一种访问方式
    console.log(student['height'])//第二种访问方式
    console.log(student['weight'])
    //因为 sayHello 是通过匿名函数实现的,所以需要跟上()
    student.sayHello()

效果展示👇

使用 { } 创建对象

属性和方法使用键值对的形式来组织.

键值对之间使用 , 分割. 最后一个属性后面的 , 可有可无

键和值之间使用 : 分割.

方法的值是一个匿名函数

使用对象的属性和方法:
javascript 复制代码
// 1. 使用 . 成员访问运算符来访问属性 `.` 可以理解成 "的"
console.log(student.name);
// 2. 使用 [ ] 访问属性, 此时属性需要加上引号
console.log(student['height']);
// 3. 调用方法, 别忘记加上 () 
student.sayHello();
2.使用new Object创建对象
javascript 复制代码
let student = new Object(); // 和创建数组类似
student.name = "CoderYanger";
student.height = 181;
student['weight'] = 120;
student.sayHello = function () {
    console.log("hello");
}
console.log(student.name);
console.log(student['weight']);
student.sayHello();

效果展示👇

注意, 使用 { } 创建的对象也可以随时使用 student.name = "CoderYanger"; 这样的方式来新增属性

代码展示👇

javascript 复制代码
    let student = {}
    student.name = "CoderYanger";
    student.height = 181;
    student['weight'] = 120;
    student.sayHello = function () {
        console.log("hello");
    }
    console.log(student.name);
    console.log(student['weight']);
    student.sayHello();

效果展示👇

3.使用构造函数创建对象

前面的创建对象方式只能创建一个一个的对象 . 而使用构造函数可以很方便 的创建 多个对象.

在 Java 中,如何去创建对象呢??我们会先去写一个 class,然后通过这个 class 去创建我们每一个对象

但是在 ES6 之前,我们是没有 class 的,那么如果我们想创建批量对象的话怎么办呢??

此时我们就引入了"构造函数",通过构造函数可以创建出来多个对象

例如: 创建几个猫咪对象

javascript 复制代码
var mimi = {
    name: "咪咪",
    type: "中华田园喵",
    miao: function () {
        console.log("喵");
   }
};
var xiaohei = {
    name: "小黑",
    type: "波斯喵",
    miao: function () {
        console.log("猫呜");
   }
}
var ciqiu = {
    name: "刺球",
    type: "金渐层",
    miao: function () {
        console.log("咕噜噜");
   }
}

代码展示👇

javascript 复制代码
    function People(name,height,weight){
        this.name = name
        this.height=height
        this.weight=weight
        this.Say = function(){
            console.log(name + "say hello")
        }
    }
    let xiaoming = new People("小明",175,75)
    let CoderYanger = new People("CoderYanger",175,75)
    console.log(xiaoming)
    xiaoming.Say()
    console.log(CoderYanger)
    CoderYanger.Say()

效果展示👇

此时写起来就比较麻烦. 使用构造函数可以把相同的属性和方法的创建提取出来, 简化开发过程

基本语法
javascript 复制代码
function 构造函数名(形参) {
    this.属性 = 值;
    this.方法 = function...
}
    
var obj = new 构造函数名(实参);

注意 :

在构造函数内部使用 this 关键字来表示当前正在构建的对象.

构造函数的函数名首字母一般是大写的.

构造函数的函数名可以是名词.

构造函数不需要 return

创建对象的时候必须使用 new 关键字

this 相当于 "我"

使用构造函数重新创建猫咪对象

javascript 复制代码
function Cat(name, type, sound) {
    this.name = name;
    this.type = type;
    this.miao = function () {
        console.log(sound); // 别忘了作用域的链式访问规则
   }
}
var mimi = new Cat('咪咪', '中华田园喵', '喵');
var xiaohei = new Cat('小黑', '波斯喵', '猫呜');
var ciqiu = new Cat('刺球', '金渐层', '咕噜噜');
console.log(mimi);
mimi.miao();

理解new关键字

new 的执行过程:

  1. 先在内存中创建一个空的对象 { }

  2. this 指向刚才的空对象(将上一步的对象作为 this 的上下文)

  3. 执行构造函数的代码, 给对象创建属性和方法

  4. 返回这个对象 (构造函数本身不需要 return, 由 new 代劳了)

参考 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new

JavaScript的对象和Java对象的区别

1.JavaScript没有"类"的概念

对象其实就是 "属性" + "方法" .

类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 "月饼模子"

在 JavaScript 中的 "构造函数" 也能起到类似的效果.

而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象

在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了

2.JavaScript对象不区分"属性"和"方法"

JavaScript 中的函数是 "一等公民", 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行

3.JavaScript对象没有private/public等访问控制机制

对象中的属性都可以被外界随意访问.

4.JavaScript对象没有继承

没有 class 也就没有继承~~

继承本质就是 "让两个对象建立关联". 或者说是让一个对象能够重用另一个对象的属性/方法.

JavaScript 中使用 "原型" 机制实现类似的效果.

例如: 创建一个 cat 对象和 dog 对象, 让这两个对象都能使用 animal 对象中的 eat 方法.

通过 proto 属性来建立这种关联关系 (proto 翻译作 "原型")

当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型中找不到, 就去原型的原型中去寻找...... 最后找到Object那里, 如果还找不到, 那就是未定义了。

关于原型链的内容比较复杂, 此处不做过多讨论

5.JavaScript没有"多态"

多态的本质在于 "程序猿不必关注具体的类型, 就能使用其中的某个方法".

C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方 法的方式 来实现多态的效果.

但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的 类型做出明确区分. 因此并不需要在语法层面上支持多态.

例如:

在 Java 中已经学过 ArrayList 和 LinkedList. 为了让程序猿使用方便, 往往写作

List<String> list = new ArrayList<>()

然后我们可以写一个方法

javascript 复制代码
void add(List<String> list, String s) {
 list.add(s);   
}

我们不必关注 list 是 ArrayList 还是 LinkedList, 只要是 List 就行. 因为 List 内部带有 add 方法.

当我们使用 JavaScript 的代码的时候

javascript 复制代码
function add(list, s) {
 list.add(s)
}

add 对于 list 这个参数的类型本身就没有任何限制. 只需要 list 这个对象有 add 方法即可. 就不必像 Java 那样先继承再重写绕一个圈子

class&构造方法

在 ES6 之前是没有 class 的,没有类

但是 ES6 中就引入了 class,我们通过一个 class 就可以把对象构造出来了

代码展示👇

javascript 复制代码
    class People{
        //构造方法
        constructor(name,height,weight){
            this.name=name;
            this.height=height;
            this.weight=weight;
        }
        Say(){
            console.log(this.name + "正在说:Hello")
        }
    }
    let CoderYanger = new People("CoderYanger",180,120)
    console.log(CoderYanger)
    CoderYanger.Say()

效果展示👇

static 关键字

在 Java 中,有些变量是属于 class 的,但不属于对象,此时怎么操作呢?定义 static 变量

代码展示👇

javascript 复制代码
    class People{
        //构造方法
        constructor(name,height,weight){
            this.name=name;
            this.height=height;
            this.weight=weight;
        }
        Say(){
            console.log(this.name + "正在说:Hello")
        }

        static other="other"
    }
    let CoderYanger = new People("CoderYanger",180,120)
    console.log(CoderYanger)
    CoderYanger.Say()
    alert(People.other)

效果展示👇

再定义一个静态方法,代码展示👇

javascript 复制代码
    class People{
        //构造方法
        constructor(name,height,weight){
            this.name=name;
            this.height=height;
            this.weight=weight;
        }
        Say(){
            console.log(this.name + "正在说:Hello")
        }
        static Sum(){
            return 100
        }
    }
    let CoderYanger = new People("CoderYanger",180,120)
    console.log(CoderYanger)
    CoderYanger.Say()
    alert(People.Sum())

效果展示👇

注意,这个方法是属于 class 的,而不属于对象,代码展示👇

javascript 复制代码
    CoderYanger.Sum()

此时就会报错,效果展示👇

继承(了解)

ES6 引入了 class 后,不但实现了构造方法,还实现了继承

代码展示👇

javascript 复制代码
    class People{
        //构造方法
        constructor(name,height,weight){
            this.name=name;
            this.height=height;
            this.weight=weight;
        }
        Say(){
            console.log(this.name + "正在说:Hello")
        }

        static Sum(){
            return 100
        }
    }
    let CoderYanger = new People("CoderYanger",180,120)
    console.log(CoderYanger)
    CoderYanger.Say()
    // CoderYanger.Sum()
    alert(People.other)
    alert(People.Sum())

    class Student extends People{
        constructor(name,height,weight,number){
            super(name,height,weight)
            this.number = number
        }
        Say(){
            alert(this.name)
        }
    }

    let student = new Student("小CoderYanger",180,120,1)
    console.log(student)
    student.Say()

效果展示👇

相关推荐
京师20万禁军教头1 小时前
39面向对象(高级)-设计模式
java·开发语言·设计模式
还是大剑师兰特1 小时前
vue项目浏览器版本判别,低于IE11跳转到新页面
前端·javascript·vue.js
rust&python1 小时前
课程表的归一化处理
python·程序人生·信息可视化
计算机魔术师1 小时前
奥尔特曼致歉 GPT-6 Astra 发布混乱,现已面向所有 Plus / Pro 等用户推出
前端
落樱弥城1 小时前
RHI 设计考量:不同 API 差异分析
服务器·前端·性能优化
白山编程大哥2 小时前
Java 迭代器接口详解:从 Iterator 到 ListIterator 的完整指南
java·开发语言·windows
热心网友俣先生2 小时前
2026国赛C题:五年命题规律与预测
java·c语言·前端·数学建模
见叶之秋2 小时前
【C++】String类的使用(含模拟实现)
java·开发语言·c++
想吃火锅10052 小时前
【leetcode】42.接雨水js
开发语言·javascript·ecmascript