11.与JavaScript深入交流-[js一篇通]
文章目录
- 1.变量的使用
- 1.1基本用法
- 1.2理解 动态类型
- 2.基本数据类型
- 2.1number 数字类型
- 2.1.1数字进制表示
- 2.1.2特殊的数字值
- 2.2string 字符串类型
- 2.2.1基本规则
- 2.2.2转义字符
- 2.2.3求长度
- 2.2.4字符串拼接
- 2.3boolean 布尔类型
- 2.4undefined 未定义数据类型
- 2.5null 空值类型
- 3.运算符
- 3.1算术运算符
- 3.2赋值运算符 & 复合赋值运算符
- 3.3自增自减运算符
- 3.4比较运算符
- 3.5逻辑运算符
- 3.6位运算
- 3.7移位运算
- 4.条件语句
- 4.1if 语句
- 4.1.1基本语法格式
- 4.1.2练习案例
- 4.2三元表达式
- 4.3switch
- 5.循环语句
- 5.1while 循环
- 5.2continue
- 5.3break
- 5.4for 循环
- 6.数组
- 6.1创建数组
- 6.2获取数组元素
- 6.3新增数组元素
- 6.3.1通过修改 length 新增
- 6.3.2通过下标新增
- 6.3.3使用 push 进行追加元素
- 6.3.4数组的三种循环遍历
- 6.4删除数组中的元素
- 7.函数
- 7.1语法格式
- 7.2关于参数个数
- 7.3函数表达式
- 7.4作用域
- 7.5作用域链
- 8.对象
- 8.1基本概念
- 8.1.1使用 字面量 创建对象 [常用]
- 8.1.2使用 new Object 创建对象
- 8.1.3使用 构造函数 创建对象
- 8.2理解 new 关键字
- 8.3JavaScript 的对象和 Java 的对象的区别
- 8.3.1JavaScript 没有 "类" 的概念
- 8.3.2JavaScript 对象不区分 "属性" 和 "方法"
- 8.3.3JavaScript 对象没有 private / public 等访问控制机制.
- 8.3.4JavaScript 对象没有 "继承"
- 8.3.5JavaScript 没有 "多态"
- 8.3.3JavaScript 对象没有 private / public 等访问控制机制.
- 8.3.4JavaScript 对象没有 "继承"
- 8.3.5JavaScript 没有 "多态"
大家好,我是晓星航。今天为大家带来的是 JavaScript语法描述 相关的讲解!😀
1.变量的使用
1.1基本用法
创建变量(变量定义/变量声明/变量初始化)
var name = 'zhangsan';
var age = 20;
var 是 JS 中的关键字, 表示这是一个变量.
= 在 JS 中表示 “赋值”, 相当于把数据放到内存的盒子中. = 两侧建议有一个空格
每个语句最后带有一个 ; 结尾. JS 中可以省略 ; 但是建议还是加上.
注意, 此处的 ; 为英文分号. JS 中所有的标点都是英文标点.
初始化的值如果是字符串, 那么就要使用单引号或者双引号引起来.
初始化的值如果是数字, 那么直接赋值即可.
使用变量
console.log(age); // 读取变量内容
age = 30; // 修改变量内容
为啥动漫中的角色都是要先喊出技能名字再真正释放技能?
就是因为变量要先声明才能使用.
代码示例: 弹框提示用户输入信息, 再弹框显示.
var name = prompt("请输入姓名:");
var age = prompt("请输入年龄:");
var score = prompt("请输入分数");
alert("您的姓名是: " + name);
alert("您的年龄是: " + age);
alert("您的分数是: " + score);
也可以把三个输出内容合并成一次弹框
var name = prompt("请输入姓名:");
var age = prompt("请输入年龄:");
var score = prompt("请输入分数");
alert("您的姓名是: " + name + "\n" + "您的年龄是: " + age + "\n" + "您的分数是: " +
score + "\n");
+
表示字符串拼接, 也就是把两个字符串首尾相接变成一个字符串.\n
表示换行
JavaScript 中还支持使用 let 定义变量. 用法和 var 基本类似. 用法上的差异此处暂时不讨论.
1.2理解 动态类型
- JS 的变量类型是程序运行过程中才确定的(运行到 = 语句才会确定类型)
var a = 10; // 数字
var b = "hehe"; // 字符串
- 随着程序运行, 变量的类型可能会发生改变.
var a = 10; // 数字
a = "hehe"; // 字符串
这一点和 C Java 这种静态类型语言差异较大.
C, C++, Java, Go 等语言是静态类型语言. 一个变量在创建的时候类型就确定了, 不能在运行时发生改变.
而 JS,python,PHP,Lua…都是动态类型,一个变量在创建的时候类型就是可以随便变化的,在运行时不能确定具体类型,但是可以发生改变类型的操作
如果尝试改变, 就会直接编译报错.
动态类型和静态类型适用的范围:
动态类型的语言特别适合初创型公司,规模小,特别赶时间。
而静态类型适合规模大,业务更稳定的公司,因为这类公司大部分时间都在做维护工作,而动态类型由于具体类型不能确定,此时维护的成本就很高(程序猿维护时因为不清楚具体类型在了解类型时会消耗更多的时间成本)
例如:字节,b站,豆瓣,知乎…这些大公司一开始也是使用 JS 来开发大型项目的(因为以前前端页面只有JS,而JS是动态类型没得选),后来 TS 火了之后,这些大厂纷纷都切换到了 TS 了。(因为TS功能更强大,且是静态类型便于后期的软件维护)
2.基本数据类型
JS 中内置的几种类型
- number: 数字. 不区分整数和小数.
- boolean: true 真, false 假.
- string: 字符串类型.
- undefined: 只有唯一的值 undefined. 表示未定义的值.
- null: 只有唯一的值 null. 表示空值.
2.1number 数字类型
JS 中不区分整数和浮点数, 统一都使用 “数字类型” 来表示.
2.1.1数字进制表示
计算机中都是使用二进制来表示数据, 而人平时都是使用十进制.
因为二进制在使用过程中不太方便(01太多会看花眼).
所以在日常使用二进制数字时往往使用 八进制 和 十六进制 来表示二进制数字.
var a = 07; // 八进制整数, 以 0 开头
var b = 0xa; // 十六进制整数, 以 0x 开头
var c = 0b10; // 二进制整数, 以 0b 开头
注意:
- 一个八进制数字对应三个二进制数字
- 一个十六进制数字对应四个二进制数字. (两个十六进制数字就是一个字节)
各种进制之间的转换, 不需要手工计算, 直接使用计算器即可.
2.1.2特殊的数字值
Infinity: 无穷大, 大于任何数字. 表示数字已经超过了 JS 能表示的范围.
-Infinity: 负无穷大, 小于任何数字. 表示数字已经超过了 JS 能表示的范围.
NaN: 表示当前的结果不是一个数字.
var max = Number.MAX_VALUE;
// 得到 Infinity
console.log(max * 2);
// 得到 -Infinity
console.log(-max * 2);
// 得到 NaN
console.log('hehe' - 10);
注意:
- 负无穷大 和 无穷小 不是一回事. 无穷小指无限趋近与 0, 值为 1 / Infinity
- ‘hehe’ + 10 得到的不是 NaN, 而是 ‘hehe10’, 会把数字隐式转成字符串, 再进行字符串拼接.
- 可以使用 isNaN 函数判定是不是一个非数字.
console.log(isNaN(10)); // false console.log(isNaN('hehe' - 10)); // true
2.2string 字符串类型
2.2.1基本规则
字符串字面值需要使用引号引起来, 单引号双引号均可.
var a = "haha";
var b = 'hehe';
var c = hehe; // 运行出错
如果字符串中本来已经包含引号咋办?
var msg = "My name is "zhangsan""; // 出错
var msg = "My name is \"zhangsan\""; // 正确, 使用转义字符. \" 来表示字符串内部的引号.
var msg = "My name is 'zhangsan'"; // 正确, 搭配使用单双引号
var msg = 'My name is "zhangsan"'; // 正确, 搭配使用单双引号
2.2.2转义字符
有些字符不方便直接输入, 于是要通过一些特殊方式来表示.
\n
\\
\'
\"
\t
2.2.3求长度
使用 String 的 length 属性即可
var a = 'hehe';
console.log(a.length);var b = '哈哈';
console.log(b.length);
结果:
4
2
单位为字符的数量
2.2.4字符串拼接
使用 + 进行拼接
var a = "my name is ";
var b = "zhangsan";
console.log(a + b);
注意, 数字和字符串也可以进行拼接
var c = "my score is ";
var d = 100;
console.log(c + d);
注意, 要认准相加的变量到底是字符串还是数字
console.log(100 + 100); // 200
console.log('100' + 100); // 100100
2.3boolean 布尔类型
表示 “真” 和 “假”
boolean 原本是数学中的概念 (布尔代数).
在计算机中 boolean 意义重大, 往往要搭配条件/循环完成逻辑判断.
Boolean 参与运算时当做 1 和 0 来看待.
console.log(true + 1);
console.log(false + 1)
这样的操作其实是不科学的. 实际开发中不应该这么写.
2.4undefined 未定义数据类型
如果一个变量没有被初始化过, 结果就是 undefined, 是 undefined 类型
var a;
console.log(a)
undefined 和字符串进行相加, 结果进行字符串拼接
console.log(a + "10"); // undefined10
undefined 和数字进行相加, 结果为 NaN
console.log(a + 10);
2.5null 空值类型
null 表示当前的变量是一个 “空值”.
var b = null;
console.log(b + 10); // 10
console.log(b + "10"); // null10
注意:
null 和 undefined 都表示取值非法的情况, 但是侧重点不同.
null 表示当前的值为空. (相当于有一个空的盒子)
undefined 表示当前的变量未定义. (相当于连盒子都没有)
3.运算符
JavaScript 中的运算符和 Java 用法基本相同. 此处不做详细介绍了.
3.1算术运算符
- +
-
-
- /
- %
3.2赋值运算符 & 复合赋值运算符
- =
- +=
- -=
- *=
- /=
- %=
3.3自增自减运算符
- ++: 自增1
- –: 自减1
3.4比较运算符
<
>
<=
>=
==
比较相等(会进行隐式类型转换)!=
===
比较相等(不会进行隐式类型转换)!==
3.5逻辑运算符
用于计算多个 boolean 表达式的值.
- && 与: 一假则假
- || 或: 一真则真
- ! 非
3.6位运算
- & 按位与
- | 按位或
- ~ 按位取反
- ^ 按位异或
3.7移位运算
- << 左移
>>
有符号右移(算术右移)>>>
无符号右移(逻辑右移)
4.条件语句
4.1if 语句
4.1.1基本语法格式
条件表达式为 true, 则执行 if 的 { } 中的代码
// 形式1
if (条件) {语句
}
// 形式2
if (条件) {语句1
} else {语句2
}
// 形式3
if (条件1) {语句1
} else if (条件2) {语句2
} else if .... {语句...
} else {语句N
}
4.1.2练习案例
代码示例1: 判定一个数字是奇数还是偶数
var num = 10;
if (num % 2 == 0) {console.log("num 是偶数");
} else {console.log("num 是奇数");
}
注意! 不能写成 num % 2 == 1 就是奇数. 负的奇数 % 2 结果可能是 -1.
代码示例2: 判定一个数字是正数还是负数
var num = 10;
if (num > 0) {console.log("num 是正数");
} else if (num < 0) {console.log("num 是负数");
} else {console.log("num 是 0");
}
代码示例3: 判定某一年份是否是闰年
var year = 2000;
if (year % 100 == 0) {// 判定世纪闰年if (year % 400 == 0) {console.log("是闰年");} else {console.log("不是闰年");}
} else {// 普通闰年if (year % 4 == 0) {console.log("是闰年");} else {console.log("不是闰年");}
}
4.2三元表达式
是 if else 的简化写法.
条件 ? 表达式1 : 表达式2
条件为真, 返回表达式1 的值. 条件为假, 返回表达式2 的值.
注意, 三元表达式的优先级是比较低的.
4.3switch
更适合多分支的场景.
switch (表达式) {case 值1:语句1;break;case 值2:语句2:break;default:语句N;
}
用户输入一个整数, 提示今天是星期几
var day = prompt("请输入今天星期几: ");
switch (parseInt(day)) {case 1:console.log("星期一");break;case 2:console.log("星期二");break;case 3:console.log("星期三");break;case 4:console.log("星期四");break;case 5:console.log("星期五");break;case 6:console.log("星期六");break;case 7:console.log("星期日");break;default:console.log("输入有误");
}
5.循环语句
重复执行某些语句
5.1while 循环
while (条件) {循环体;
}
执行过程:
- 先执行条件语句
- 条件为 true, 执行循环体代码.
- 条件为 false, 直接结束循环
代码示例1: 打印 1 - 10
var num = 1;
while (num <= 10) {console.log(num);num++;
}
代码示例2: 计算 5 的阶乘
var result = 1;
var i = 1;
while (i <= 5) {result *= i;i++;
}
console.log(result)
5.2continue
可以跳过本次循环剩余代码,执行下一次循环。
吃五个李子, 发现第三个李子里有一只虫子, 于是扔掉这个, 继续吃下一个李子.
var i = 1;
while (i <= 5) {if (i == 3) {i++;continue;}console.log("我在吃第" + i + "个李子");i++;
}
我在吃第1个李子
我在吃第2个李子
我在吃第4个李子
我在吃第5个李子
代码示例: 找到 100 - 200 中所有 3 的倍数
var num = 100;
while (num <= 200) {if (num % 3 != 0) {num++; // 这里的 ++ 不要忘记! 否则会死循环. continue;}console.log("找到了 3 的倍数, 为:" + num);num++;
}
5.3break
结束整个循环
吃五个李子, 发现第三个李子里有半个虫子, 于是剩下的也不吃了.
var i = 1;
while (i <= 5) {if (i == 3) {break;}console.log("我在吃第" + i + "个李子");i++;
}
我在吃第1个李子
我在吃第2个李子
代码示例: 找到 100 - 200 中第一个 3 的倍数
var num = 100;
while (num <= 200) {if (num % 3 == 0) {console.log("找到了 3 的倍数, 为:" + num);break;}num++;
}
// 执行结果
找到了 3 的倍数, 为:102
5.4for 循环
for (表达式1; 表达式2; 表达式3) {循环体
}
- 表达式1: 用于初始化循环变量.
- 表达式2: 循环条件
- 表达式3: 更新循环变量.
执行过程:
- 先执行表达式1, 初始化循环变量
- 再执行表达式2, 判定循环条件
- 如果条件为 false, 结束循环
- 如果条件为 true, 则执行循环体代码.
- 执行表达式3 更新循环变量
代码示例1: 打印 1 - 10 的数字
for (var num = 1; num <= 10; num++) {console.log(num);
}
代码示例2: 计算 5 的阶乘
var result = 0;
for (var i = 1; i <= 5; i++) {result *= i;
}
console.log("result = " + result);
6.数组
6.1创建数组
使用 new 关键字创建
// Array 的 A 要大写
var arr = new Array();
使用字面量方式创建 [常用]
var arr = [];
var arr2 = [1, 2, 'haha', false]; // 数组中保存的内容称为 "元素"
注意: JS 的数组不要求元素是相同类型.
这一点和 C, C++, Java 等静态类型的语言差别很大. 但是 Python, PHP 等动态类型语言也是如此.
6.2获取数组元素
使用下标的方式访问数组元素(从 0 开始)
var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
console.log(arr);
console.log(arr[0]);
console.log(arr[1]);
console.log(arr[2]);
arr[2] = '小猫凯迪';
console.log(arr);
如果下标超出范围读取元素, 则结果为 undefined
console.log(arr[3]); // undefined
console.log(arr[-1]); // undefined
虽然数组越界了,但是代码还是正常运行,没有说报错崩溃。
注意: 不要给数组名直接赋值, 此时数组中的所有元素都没了.
arr[100] = '小狗黄能';
console.log(arr);
这里我们看到,虽然直接打印arr[3]越界了,但是我们设置 arr[100]='小狗黄能';
之后,我们的数组长度变为了100。
arr['hello']='廉小猫';
console.log(arr);
这里我们的代码为什么可以用字符来当数组下标???
注意我们这里的字符不是单纯的字符了,而是键值对,不如理解成 数组 + Map 的混血儿。
相当于本来 arr 是一个数组, 重新赋值后变成字符串了.
var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
arr = '小猫凯迪';
6.3新增数组元素
6.3.1通过修改 length 新增
相当于在末尾新增元素. 新增的元素默认值为 undefined
var arr = [9, 5, 2, 7];
arr.length = 6;
console.log(arr);
console.log(arr[4], arr[5]);
6.3.2通过下标新增
如果下标超出范围赋值元素, 则会给指定位置插入新元素
var arr = [];
arr[2] = 10;
console.log(arr)
此时这个数组的 [0] 和 [1] 都是 undefined
6.3.3使用 push 进行追加元素
代码示例一: 给定一个数组, 把数组中的奇数放到一个 newArr 中.
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);
代码示例二:
var arr = ['小猪佩奇', '小猪乔治', '小羊苏西'];
arr.push('小狗黄能');
for (var i = 0; i < arr.length; i++) {console.log(arr[i]);
}
6.3.4数组的三种循环遍历

6.4删除数组中的元素
使用 splice 方法删除元素
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() 使用的时候带括号, 并且可以传参数, 此时是一个函数 (也叫做方法)
7.函数
7.1语法格式
// 创建函数/函数声明/函数定义
function 函数名(形参列表) {函数体return 返回值;
}
// 函数调用
函数名(实参列表) // 不考虑返回值
返回值 = 函数名(实参列表) // 考虑返回值
- 函数定义并不会执行函数体内容, 必须要调用才会执行. 调用几次就会执行几次.
function hello() {console.log("hello");
}
// 如果不调用函数, 则没有执行打印语句
hello();
- 调用函数的时候进入函数内部执行, 函数结束时回到调用位置继续执行. 可以借助调试器来观察.
- 函数的定义和调用的先后顺序没有要求. (这一点和变量不同, 变量必须先定义再使用)
// 调用函数
hello();
// 定义函数
function hello() {console.log("hello");
}
7.2关于参数个数
实参和形参之间的个数可以不匹配. 但是实际开发一般要求形参和实参个数要匹配
- 如果实参个数比形参个数多, 则多出的参数不参与函数运算
sum(10, 20, 30); // 30
- 如果实参个数比形参个数少, 则此时多出来的形参值为
sum(10); // NaN, 相当于 num2 为 undefined.
NaN:意为not a number (不是一个数字)
undefined JS 的函数传参比较灵活, 这一点和其他语言差别较大. 事实上这种灵活性往往不是好事.
7.3函数表达式
另外一种函数的定义方式
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 变量来调用函数了.
JS 中函数是一等公民, 可以用变量保存, 也可以作为其他函数的参数或者返回值.
7.4作用域
某个标识符名字在代码中的有效范围.
在 ES6 标准之前, 作用域主要分成两个
- 全局作用域: 在整个 script 标签中, 或者单独的 js 文件中生效.
- 局部作用域/函数作用域: 在函数内部生效.
// 全局变量
var num = 10;
console.log(num);
function test() {// 局部变量var num = 20;console.log(num);
}
function test2() {// 局部变量var num = 30;console.log(num);
}
test();
test2();
console.log(num);
// 执行结果
10
20
30
10
创建变量时如果不写 var, 则得到一个全局变量.
function test() {num = 100; } test(); console.log(num); // 执行结果 100
另外, 很多语言的局部变量作用域是按照代码块(大括号)来划分的, JS 在 ES6 之前不是这样的.
if (1 < 2) {var a = 10; } console.log(a);
这两个代码区别就是 第1个代码:一个是返回到另一个函数继续执行,而 第2个代码:另一个是直接返回另一个函数的结果。
js 中变量的作用域,当代码中访问某个变量的时候,要去哪里找这个变量,js 会先找当前作用域,如果当前作用域没有,就往上层作用域找,一直往上直到全局作用域。如果还找不到,报错/undefined
7.5作用域链
背景:
- 函数可以定义在函数内部
- 内层函数可以访问外层函数的局部变量.
内部函数可以访问外部函数的变量. 采取的是链式查找的方式. 从内到外依次进行查找.
var num = 1;
function test1() {var num = 10;function test2() {var num = 20;console.log(num);}test2();
}
test1();
// 执行结果
20
执行 console.log(num) 的时候, 会现在 test2 的局部作用域中查找 num. 如果没找到, 则继续去 test1 中 查找. 如果还没找到, 就去全局作用域查找.
var num = 1;function test1() {var num = 2;function test2() {var num = 3;console.log("test2: " + num);}test2();console.log("test1: " + num);}test1();console.log("global: " + num);
8.对象
8.1基本概念
对象是指一个具体的事物.
“电脑” 不是对象, 而是一个泛指的类别. 而 “我的联想笔记本” 就是一个对象.
在 JS 中, 字符串, 数值, 数组, 函数都是对象.
每个对象中包含若干的属性和方法.
- 属性: 事物的特征.
- 方法: 事物的行为.
例如, 你有一个女票.
她的身高体重三围这些都是属性.
她的唱歌, 跳舞, 暖床都是方法.
对象需要保存的属性有多个, 虽然数组也能用于保存多个数据, 但是不够好.
例如表示一个学生信息. (姓名蔡徐坤, 身高 175cm, 体重 170斤)
var student = [‘蔡徐坤’, 175, 170];
但是这种情况下到底 175 和 170 谁表示身高, 谁表示体重, 就容易分不清
JavaScript 的对象 和 Java 的对象概念上基本一致. 只是具体的语法表项形式差别较大.
8.1.1使用 字面量 创建对象 [常用]
使用 { } 创建对象
var a = {}; // 创建了一个空的对象
var student = {name:'蔡徐坤',age: 25,height:180,weight:70,sing: function() {console.log("鸡你太美");},dance: function() {console.log("铁山靠");},rap: function() {console.log("你是我是你的谁?");}
};
- 使用 { } 创建对象
- 属性和方法使用键值对的形式来组织.
- 键值对之间使用 , 分割. 最后一个属性后面的 , 可有可无
- 键和值之间使用 : 分割.
- 方法的值是一个匿名函数.
使用对象的属性和方法:
// 1. 使用 . 成员访问运算符来访问属性 `.` 可以理解成 "的"
console.log(student.name);
// 2. 使用 [ ] 访问属性, 此时属性需要加上引号
console.log(student['height']);
// 3. 调用方法, 别忘记加上 ()
student.sayHello();
eg:
var student = {name:'蔡徐坤',age: 25,height:180,weight:70,sing: function() {console.log("鸡你太美");},dance: function() {console.log("铁山靠");},rap: function() {console.log("你是我是你的谁?");}
};
console.log(student.name);
console.log(student.age);
student.sing();
8.1.2使用 new Object 创建对象
var student = new Object();// 和创建数组类似
student.name = '蔡徐坤';
student.age = 25;
student['weight'] = 120;
student.sing = function(){console.log("鸡你太美");
};
console.log(student.name);
console.log(student.age);
console.log(student.weight);
student.sing();
注意, 使用 { } 创建的对象也可以随时使用 student.name = "蔡徐坤";
这样的方式来新增属性.
8.1.3使用 构造函数 创建对象
前面的创建对象方式只能创建一个对象. 而使用构造函数可以很方便 的创建 多个对象.
例如: 创建几个猫咪对象
var mimi = {name: "咪咪",type: "中华田园喵",miao: function () {console.log("喵");}
};
var xiaohei = {name: "小黑",type: "波斯喵",miao: function () {console.log("猫呜");}
}
var ciqiu = {name: "刺球",type: "金渐层",miao: function () {console.log("咕噜噜");}
}
此时写起来就比较麻烦. 使用构造函数可以把相同的属性和方法的创建提取出来, 简化开发过程.
基本语法
function 构造函数名(形参) {this.属性 = 值;this.方法 = function...
}var obj = new 构造函数名(实参);
注意:
- 在构造函数内部使用 this 关键字来表示当前正在构建的对象.
- 构造函数的函数名首字母一般是大写的.
- 构造函数的函数名可以是名词.
- 构造函数不需要 return
- 创建对象的时候必须使用 new 关键字.
this 相当于 “我”
使用构造函数重新创建猫咪对象
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();
8.2理解 new 关键字
new 的执行过程:
- 先在内存中创建一个空的对象 { }
- this 指向刚才的空对象(将上一步的对象作为 this 的上下文)
- 执行构造函数的代码, 给对象创建属性和方法
- 返回这个对象 (构造函数本身不需要 return, 由 new 代劳了)
参考:[new运算符解析](new 运算符 - JavaScript | MDN (mozilla.org))
8.3JavaScript 的对象和 Java 的对象的区别
8.3.1JavaScript 没有 “类” 的概念
对象其实就是 “属性” + “方法” .
类相当于把一些具有共性的对象的属性和方法单独提取了出来, 相当于一个 “月饼模子”
在 JavaScript 中的 “构造函数” 也能起到类似的效果.
而且即使不是用构造函数, 也可以随时的通过 { } 的方式指定出一些对象
在 ES6 中也引入了 class 关键字, 就能按照类似于 Java 的方式创建类和对象了.
8.3.2JavaScript 对象不区分 “属性” 和 “方法”
JavaScript 中的函数是 “一等公民”, 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.
8.3.3JavaScript 对象没有 private / public 等访问控制机制.
对象中的属性都可以被外界随意访问.
8.3.4JavaScript 对象没有 “继承”
继承本质就是 “让两个对象建立关联”. 或者说是让一个对象能够重用另一个对象的属性/方法.
JavaScript 中使用 “原型” 机制实现类似的效果.
例如: 创建一个 cat 对象和 dog 对象, 让这两个对象都能使用 animal 对象中的 eat 方法.
通过 __proto__
属性来建立这种关联关系 (proto 翻译作 “原型”)
当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型 中找不到, 就去原型的原型中去寻找… 最后找到Object那里, 如果还找不到, 那就是未定义了。
关于原型链的内容比较复杂, 此处不做过多讨论
8.3.5JavaScript 没有 “多态”
多态的本质在于 “程序猿不必关注具体的类型, 就能使用其中的某个方法”.
C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方 法的方式 来实现多态的效果.
但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的类 型做出明确区分. 因此并不需要在语法层面上支持多态.
例如:
在 Java 中已经学过 ArrayList 和 LinkedList. 为了让程序猿使用方便, 往往写作
List list = new ArrayList<>()
然后我们可以写一个方法:
void add(List<String> list, String s) {list.add(s); }
我们不必关注 list 是 ArrayList 还是 LinkedList, 只要是 List 就行. 因为 List 内部带有 add 方法.
当我们使用 JavaScript 的代码的时候
function add(list, s) {list.add(s) }
add 对于 list 这个参数的类型本身就没有任何限制. 只需要 list 这个对象有 add 方法即可. 就不必 像 Java 那样先继承再重写绕一个圈子.
“一等公民”, 和普通的变量一样. 存储了函数的变量能够通过 ( ) 来进行调用执行.
8.3.3JavaScript 对象没有 private / public 等访问控制机制.
对象中的属性都可以被外界随意访问.
8.3.4JavaScript 对象没有 “继承”
继承本质就是 “让两个对象建立关联”. 或者说是让一个对象能够重用另一个对象的属性/方法.
JavaScript 中使用 “原型” 机制实现类似的效果.
例如: 创建一个 cat 对象和 dog 对象, 让这两个对象都能使用 animal 对象中的 eat 方法.
通过 __proto__
属性来建立这种关联关系 (proto 翻译作 “原型”)
[外链图片转存中…(img-ZCVFCBcm-1698739596171)]
当eat方法被调用的时候,先在自己的方法列表中寻找, 如果找不到,就去找原型中的方法, 如果原型 中找不到, 就去原型的原型中去寻找… 最后找到Object那里, 如果还找不到, 那就是未定义了。
[外链图片转存中…(img-miSAhFQg-1698739596171)]
关于原型链的内容比较复杂, 此处不做过多讨论
8.3.5JavaScript 没有 “多态”
多态的本质在于 “程序猿不必关注具体的类型, 就能使用其中的某个方法”.
C++ / Java 等静态类型的语言对于类型的约束和校验比较严格. 因此通过 子类继承父类, 并重写父类的方 法的方式 来实现多态的效果.
但是在 JavaScript 中本身就支持动态类型, 程序猿在使用对象的某个方法的时候本身也不需要对对象的类 型做出明确区分. 因此并不需要在语法层面上支持多态.
例如:
在 Java 中已经学过 ArrayList 和 LinkedList. 为了让程序猿使用方便, 往往写作
List list = new ArrayList<>()
然后我们可以写一个方法:
void add(List<String> list, String s) {list.add(s); }
我们不必关注 list 是 ArrayList 还是 LinkedList, 只要是 List 就行. 因为 List 内部带有 add 方法.
当我们使用 JavaScript 的代码的时候
function add(list, s) {list.add(s) }
add 对于 list 这个参数的类型本身就没有任何限制. 只需要 list 这个对象有 add 方法即可. 就不必 像 Java 那样先继承再重写绕一个圈子.
感谢各位读者的阅读,本文章有任何错误都可以在评论区发表你们的意见,我会对文章进行改正的。如果本文章对你有帮助请动一动你们敏捷的小手点一点赞,你的每一次鼓励都是作者创作的动力哦!😘
相关文章:

11.与JavaScript深入交流-[js一篇通]
文章目录 1.变量的使用1.1基本用法1.2理解 动态类型 2.基本数据类型2.1number 数字类型2.1.1数字进制表示2.1.2特殊的数字值 2.2string 字符串类型2.2.1基本规则2.2.2转义字符2.2.3求长度2.2.4字符串拼接 2.3boolean 布尔类型2.4undefined 未定义数据类型2.5null 空值类型 3.运…...

Ubuntu 搭建 DHCP ivp6 server 步骤
Ubuntu 搭建 DHCP ivp6 server 步骤 安装 DHCP server安装 radvd(实现局域网路由功能)测试运行 安装 DHCP server apt 安装 isc-dhcp-server sudo apt-get install isc-dhcp-server修改配置文件 /etc/dhcp/dhcpd6.conf 内容如下: lease-time 7200; lo…...

分享大数据分析师前景怎么样? 从事行业有哪些?
数据分析师发展前景和待遇怎么样?有前途吗?好找工作吗?根据某招聘网数据显示,当前市场表现为: 2023年较2022年同期对比增长160%,2022年较2021年下降了46%。 工资待遇:2023年较2022年下降了2…...

通过wordpress能搭建有影响力的帮助中心
wordpress建站服务是一种提供简单易用的工具和功能,帮助用户轻松创建和管理网站的服务。它适用于各类网站管理员、个人博主和小型企业主,无论是想要搭建个人博客、展示作品集还是开设在线商店,都可以通过wordpress建站服务来实现。 | 一、搭建…...

word页脚设置,页脚显示第几页共有几页设置步骤
word页脚设置,页脚显示第几页共有几页设置步骤: 具体步骤: 步骤1: 步骤1.1选择页脚---空白页脚 步骤1.2,在"[在此处键入]",直接输入你需要的格式,如 “第页/共页” 步骤1.3选择第“…...

C语言实现斐波那契数列的多种方法
斐波那契数列(Fibonacci sequence),又称黄金分割数列,因数学家莱昂纳多斐波那契(Leonardo Fibonacci)以兔子繁殖为例子而引入,故又称为“兔子数列”。对于解决此类问题方法有四,前两…...

一文解决:Swagger API 未授权访问漏洞问题
Swagger 是一个用于设计、构建、文档化和使用 RESTful 风格的 Web 服务的开源软件框架。它通过提供一个交互式文档页面,让开发者可以更方便地查看和测试 API 接口。然而,在一些情况下,未经授权的访问可能会导致安全漏洞。本文将介绍如何解决 …...

Elasticsearch下载安装,IK分词器、Kibana下载安装使用,elasticsearch使用演示
首先给出自己使用版本的网盘链接:自己的版本7.17.14 链接:https://pan.baidu.com/s/1FSlI9jNf1KRP-OmZlCkEZw 提取码:1234 一般情况下 Elastic Search(ES) 并不单独使用,例如主流的技术组合 ELK(…...
springboot自定义404页面
添加配置类 import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import javax.servlet.Servlet; import org.apache.catalina.startup.Tomcat; import org.apache.catalina.valves.ErrorReportValve; import org.apache.coyote.UpgradeProtoc…...

C/C++数据结构之时间复杂度和空间复杂度详细解析以及力扣刷题
个人主页:点我进入主页 专栏分类:C语言初阶 C语言程序设计————KTV C语言小游戏 C语言进阶 C语言刷题 数据结构初阶 欢迎大家点赞,评论,收藏。 一起努力,一起奔赴大厂。 目录 1.前言 2.算法的…...

【需要理解】80 单词搜索
单词搜索 题解1 回溯(需要改变起点) 给定一个 m x n 二维字符网格 board 和一个字符串单词 word 。如果 word 存在于网格中,返回 true ;否则,返回 false 。 单词必须按照字母顺序,通过相邻的单元格内…...

笔记本电脑的键盘鼠标如何共享控制另外一台电脑
环境: 联想E14 x2 Win10 across 2.0 问题描述: 笔记本电脑的键盘鼠标如何共享控制另外一台电脑 解决方案: 1.下载across软件,2台电脑都按装,一台设为服务端,一台客户端 2.把配对好设备拖到右边左侧…...

【计算机网络】(谢希仁第八版)第二章课后习题答案
第二章 1.物理层要解决哪些问题?物理层的主要特点是什么? 答:物理层要解决的主要问题: (1)物理层要尽可能地屏蔽掉物理设备和传输媒体,通信手段的不同,使数据链路层感觉不到这些差…...

笔记软件Notability mac中文版软件功能
Notability mac是一款帮助用户备注文件的得力工具,Notability Mac版可用于注释文稿、草拟想法、录制演讲、记录备注等。它将键入、手写、录音和照片结合在一起,便于您根据需要创建相应的备注。 Mac Notability mac中文版软件功能 将手写,照片…...

【C++的OpenCV】第十四课-OpenCV基础强化(三):Mat元素的访问之data和step属性
🎉🎉🎉 欢迎来到小白 p i a o 的学习空间! \color{red}{欢迎来到小白piao的学习空间!} 欢迎来到小白piao的学习空间!🎉🎉🎉 💖 C\Python所有的入门技术皆在 我…...

Springmvc 讲解(1)
文章目录 前言一、SpringMvc1、简介2、核心组件和调用流程2.1 涉及组件的理解 3、小案例快速体验3.1场景需求3.1.1 导入依赖3.1.2 controller声明3.1.3 核心配置类3.1.4 环境搭建3.1.6 配置tomcat3.1.7 测试 二、SpringMvc 接收参数1.路径设置注解2、param接收参数四种类型2.1 …...

超级英雄的导航之旅:动态路由和嵌套路由
🤍 前端开发工程师(主业)、技术博主(副业)、已过CET6 🍨 阿珊和她的猫_CSDN个人主页 🕠 牛客高级专题作者、在牛客打造高质量专栏《前端面试必备》 🍚 蓝桥云课签约作者、已在蓝桥云…...
发现个好玩的 Windows微信对话框换行
按住shift键按enter就是换行 直接按enter为发送...

Vue3最佳实践 第八章 ESLint 与 测试 ( Jest )
Jest 测试 Vue 组件 在前端项目开发过程中,有很多时候也会要进行测试工作。本文将重点介绍如何利用 JavaScript 测试框架 Jest 进行高效的测试。Jest 是由 FaceBook 开发的顶级测试框架之一,广受开发者们的欢迎和信赖。在接下来的内容中,我…...

【抓包分析】通过ChatGPT解密还原某软件登录算法实现绕过手机验证码登录
文章目录 🍋前言实现效果成品广告抓包分析一、定位加密文件二、编辑JS启用本地替换 利用Chatgpt进行代码转换获取计划任务id模拟数据请求最后 🍋前言 由于C站版权太多,所有的爬虫相关均为记录,不做深入! 今天发现gith…...

C++实现分布式网络通信框架RPC(3)--rpc调用端
目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中,我们已经大致实现了rpc服务端的各项功能代…...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...
ubuntu搭建nfs服务centos挂载访问
在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...

ETLCloud可能遇到的问题有哪些?常见坑位解析
数据集成平台ETLCloud,主要用于支持数据的抽取(Extract)、转换(Transform)和加载(Load)过程。提供了一个简洁直观的界面,以便用户可以在不同的数据源之间轻松地进行数据迁移和转换。…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...
Spring AI 入门:Java 开发者的生成式 AI 实践之路
一、Spring AI 简介 在人工智能技术快速迭代的今天,Spring AI 作为 Spring 生态系统的新生力量,正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务(如 OpenAI、Anthropic)的无缝对接&…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程
本文较长,建议点赞收藏,以免遗失。更多AI大模型应用开发学习视频及资料,尽在聚客AI学院。 本文全面剖析RNN核心原理,深入讲解梯度消失/爆炸问题,并通过LSTM/GRU结构实现解决方案,提供时间序列预测和文本生成…...

算法笔记2
1.字符串拼接最好用StringBuilder,不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...