JavaScript学习笔记(一)

本文只是教程的部分摘录笔记,如想系统学习JavaScript,请访问现代JavaScript教程

0 JavaScript代码的插入

使用JavaScript代码有两种形式

一种是在<script>和</script>标签之间直接写入JavaScript代码。

<script>
//代码部分
</script>

另一种是将JavaScript代码写入.js文件,再通过src属性导入。

<script src="test.js"></script>

注意:两种方法不能同时使用!

一般多使用第二种方法导入JavaScript代码。这样浏览器会将JavaScript代码文件下载到缓存中,再次使用该代码文件时浏览器会直接从缓存中调用,极大提高了加载速度。

1 语句

JavaScript语句和C语言类似,“ ; ”标志着语句的结束。

alert("Hello World!");  // alert语句可以在浏览器中弹出提示框,重点是;结尾

2 注释

JavaScript的注释也和C语言类似,使用" // "作为一行的注释,使用" /* "和" */ "组合来进行跨行多段注释。

alert("test") // 这是一行注释

/*
这是大块注释的第一行
这是第二行
第三行
*/

在大多数编辑器中,选中一行代码按下“Ctrl + /”可以进行快速行注释。按下“Ctrl + Shift + /”可以进行快速多段代码注释。

3 现代模式

由于JavaScript的不断迭代更新,许多旧的特性或被修改,或被取消。为了保证兼容性,JavaScript默认不启用这些的修改。但使用“use strict”语句可以强制启用这些修改。

“use strict”;  

“use strict”语句必须放在整个文件的最顶端,这样才能启用现代模式。

4 变量

JavaScript的变量声明和C语言类似,但也有些许不同。JavaScript使用“ let "来声明变量,但它不需要像C语言一样准确的声明诸如” int “, " char "等变量类型。

let message;  // 语句同样使用;结尾

message = "test";  // 给变量赋值

alert(message);  // 还记得alert的作用吗?

在查看其他程序员的代码时,可能会遇见使用“ var ”来声明变量。这是比较老派的做法,目前推荐使用let来声明变量。

变量命名规则同C语言,这里不再赘述。

使用" const "可以声明常量,其值不能改变,在代码中适当的使用可以增强程序的可读性,

const number = 1;

5 数据类型

JavaScript中有8中数据类型。

5.0 Number类型

Number类型代表整数和浮点数。

Infinity代表数学中的无穷大。

NaN代表错误的计算结果。

alert("This is not a number" / 2)  // 返回NaN

BigInt代表大整数,即大于(253-1)(即 9007199254740991),或小于 -(253-1) 的整数。

5.1 String类型

即字符串类型,其有三种表示

单引号表示:'String'

双引号表示:"String"

反引号表示:`String`

其中,反引号允许在字符串中引入变量:

const name = "LiMing";  // const定义常量

let test;  // let定义变量

test = `My name is ${name}`;  // 在字符串中引入name

alert(test);  // 弹出提示框测试

如果嵌入的是表达式,则会先计算表达式的值再嵌入:

let test;  // 声明变量

test = `1 + 2 = ${1 + 2}`;  // 嵌入表达式

alert(test);  // 弹出测试框测试

值得注意的是,只有反引号才允许引入变量,在单引号和双引号中引入变量均会报错。

5.2 Boolean类型(逻辑类型)

即" true "和" False ",这里不再赘述。

5.3 Null值

Null是一个空值,它代表什么都没有。

let age = null;  // 代表age是未知的

5.4 undefined值

undefined代表变量已声明但未赋值。

5.5 object类型和symbol类型

后续会详细介绍。

5.6 typeof运算符

typeof运算符可以返回参数的类型,它有两种调用形式:

typeof x;  // 运算符形式

typeof(x);  // 函数形式

两者返回的结果没有区别。

6 交互

6.0 alert

在前面例子中已经出现过,其会产生一个提示框,用户在解决完提示框之前不能点击网页的其他位置。对alert的调用会返回undefined。

alert("Hello World!");  // 梦回初始

6.1 prompt

prompt函数的作用是弹出提示框,并要求用户输入信息并返回,如果用户不输入信息或者点击取消,则会返回null。

它接受两个参数:

reuslt = prompt(title, [default]);

其中,title代表弹出提示框中的提示信息,[default]参数是可选的,它代表默认返回该值,如果不设置,则返回null。

let age;

age = prompt("How old are you?", 100);  // 向用户索要输入

alert(`You are ${age} years old!`);  // 默认返回 You are 100 years old.

注意:一般来说为保证兼容性,最好加上default参数。

6.2 confirm

confirm函数可以弹出提示信息,要求用户选择“确定”或“取消”,并相应的返回“true”或“false”。

result = confirm(question);

此函数接受一个参数question,代表弹出的提示信息。

例如:

let result = confirm("Do you want to exit?");

alert(result);

7 类型转换

7.1 字符类型转换

使用String()可以将变量强制转换为字符类型的变量。

let number = 3;

number = String(number);

alert(typeof number);

7.2 数字类型转换

使用Number()可以将变量强制转换为数字类型的变量。

let string1 = "1";

string1 = Number(string1);

alert(typeof string1);

如果该字符不是有效的数字,则会返回NaN。

let string2 = "This is not a numebr";

string2 = Number(string2);

alert(string2);  // NaN

Number转换规则:

转换前转换后
undefinedNaN
null0
true1
false0
string去掉首尾空格后进行转换,如果剩余为空字符,则返回0。如果剩余字符中仍有非数字,则返回NaN。

7.3 布尔类型转换

使用boolean()可以将变量转换为布尔类型。

只有0、空字符串、null、NaN、undefined会被转换为false,

其余均会被转换为true。

8 基础运算符

8.0 ' + '的特殊用法

在JS中,' + '可以用来连接两个字符:

let string1 = 'My',
    string2 = 'string',
    string3 = string1 + string2;

alert(string3);  // Mystring

只要任意一个元素是字符,则另一个元素也会被转化成字符,然后进行连接;

let string1 = 'string' + 1;

alert(string1);  // string1

8.1 神奇的"++"

"++"运算符有前置和后置两种形式。"++"在后则返回操作前的值,"++"在前则返回操作后的值。最后a, b的值都是1。


let a = 0;

alert(a++);  // 显示0

let b = 0;

alert(++b);  // 显示1

alert(a);  // 1
alert(b);  // 1

9 值的比较

0)在进行字符串比较时,JS会按照Unicode编码顺序逐位进行比较。

1)对于不同类型的变量之间的比较,JS会将其全部转化为Number类型再判定大小

2)使用' === '可以要求JS不进行变量转换的比较,即严格比较。如果被比较的数据类型不同,则会返回false。

3)null==undefined 返回的是true

10 条件语句

if, else, else if 同C语言。

10.0 三元运算符" ? "

let result = condition ? value1 : value2;

conditon代表条件,如果" ? "之前为true,则执行value1,否则执行value2。

在某些情况下," ? "可以减少代码量,比如:

let access;
let age = prompt("How old are you?", 18);

if(age>=18)
{
    access = true;
}
else{
    access = false;
}

可以简化为:

let access;
let age = prompt("How old are you?", 18);

access = (age > 18) ? true: false;

" ? "同样也可以进行嵌套使用。

11 逻辑运算符

11.0 ||

" || "运算符可以返回表达式中第一个真值,如果没有真值,则返回最后一个值。

let name = "" || "LiMing" || "LiHua";  // 空字符串会被转换为false

alert(name);  // LiMing
let number = false || false || 0;

alert(number); // 0

11.1 &&

" && "运算符可以返回表达式中第一个假值,如果没有假值,则返回最后一个值。

11.2 ??

" ?? "是空值合并运算符。表达式

a ?? b

如果a未定义,则表达式返回b的值;

如果a已定义,则表达式返回a的值。

常用来设置默认值。

12 循环

for, while, switch 同C语言

12.0 switch

放在一起的case语句可以共享同一段代码,本质是利用case后未加break导致的代码粘连。

let a = 0;
		
switch(3)
{
	case 1:
	case 2: // 1和2共享同一段代码
		alert(wrong!);
		break;
		
    case 3:
		alert(right!);
		break;
}
	

case的相等是严格相等,即数据类型也必须相同

13 函数

13.0 函数格式

function name(parameters) {
  ...body...
}

其先使用function声明这是一个函数,后面是此函数的名字,圆括号内是函数需要传入的参数,花括号内是函数体。

13.1 函数的参数

调用函数时如果传入的参数不够,则未传入参数的变量的值为undefined

function ShowMessage(user, message)
{
	alert(typeof message);
}

ShowMessage("LiMing"); // undefined

同样,函数也可以设定参数的默认值。

function ShowMessage(message = "200 OK")
{
	alert(message);
}

ShowMessage(); // 200 OK
ShowMessage("404 Not Found")  // 404 not found

13.2 函数的返回值

如果return后面没有其他语句,则其等价于return undefined,函数会返回undefined。

function Test()
{	
	return;
}

alert(typeof(Test())); // undefined

13.3 函数的声明和表达式

JS引擎在执行脚本时,首先会搜索整个脚本中的函数的声明并创建函数,这使得函数声明创建的函数无论在脚本的哪个位置都能使用。

但函数表达式只有在被执行到时会被创建,因此会出现顺序问题。

现代模式下,函数声明只在当前所在的代码块中可用。

13.4 箭头函数

对于一些简单的函数,我们可以使用箭头函数来替代。其形式如下:

let func = (arg1, arg2, ...argN) => expression

等价于:

let func = function(arg1, arg2, ...argN) {
    return expression;
};

例如,求两个数之和的函数如下:

let sum = function(a, b) {
    return a + b;
};

使用箭头函数则可以表示为:

let sum = (a, b) => a + b;

如果只有一个参数,则可以省略括号:

let func = n => n ** 2;

如果没有参数,则必须加上括号:

let func = () => alert("Hello!");

因此,在使用一些简单的函数时可以用箭头函数减小代码量。

箭头函数的多行形式

如果 => 右边有多行表达式,则应该用 { } 包裹并使用return语句返回值

let func = (a, b) => {
    let result = a + b;
    return result;
};

14 对象

JS中对象包括键值对,键必须是字符串类型或Symbol类型,使用其他类型的变量会被自动转换为字符类型,值可以使任意类型的数据。

14.0 对象的基本知识

创建对象

使用 {} 即可创建对象:

let user = {};

这里的user就是一个对象。

创建对象时可以给其直接添加属性, :

let user = {
    name : "LiMing",
    age : 18,
};

键也可以使用长字符,但必须使用引号包裹:

let user = {
    name : "LiMing",
    "like bird" : false,  // 使用长字符作为键
}

属性必须以 , 结尾,这样可以方便的显式添加或删除属性:

user.weight = 60;  // 添加属性

user.name = "LiHua";  // 修改属性

delete user.age;  // 删除属性

一般来说,通过 . 操作符就可以访问对象的属性,其要求属性的键是合法的字符串。因此,对于不合法的字符串,我们需要通过 [ ] 来进行访问:

alert( user.like bird )  // 错误的写法

alert( user["like bird"] )  // √

使用 [ ] 还可以通过变量名来访问属性,而 . 操作符不可以:

let user = {
    name : "LiMing",
}

let key = prompt("What do you want to know about the user?", "name");

alert( user[key] );  // LiMing

alert( user.key )  // 错误

计算属性

因为 [ ] 操作符,我们可以动态的创建属性:

let fruit = prompt("which fruit do you have?", "apple");

let user = {
    [fruit] : 5,
}

alert( user[fruit] );

 [ ] 中还支持字符运算:

let fruit = prompt("which fruit do you have?", "apple");

let user = {
    [fruit + "computer"] : 5,  // applecomputer : 5
}

alert( user[fruit] );

属性值简写

在实际应用中,常用变量名来作为属性值:

function make_user(name, age){
    return {
        name : name,
        age : age,
    }
}

let user = make_user("LiMing", 18);

alert( user.name );  // LiMing

其可以简写如下:

function make_user(name, age){
    return {
        name,  // 这里的name代表 name : name,即键和值同名
        age,
    }
}

let user = make_user("LiMing", 18);

alert( user.name );  // LiMing

属性存在测试:in 操作符

在JS中,如果读取的属性不存在,则会返回undefined。

使用 in 操作符可以测试该对象中有无此属性。

function make_user(name, age){
    return {
        name,
        age,
    }
}

let user = make_user("LiMing", 18);

alert( "name" in user );  // true

值得注意的是,in 左边必须是字符串,如果是形参,则该形参所指向的实参必须为字符类型。

for...in...循环

为了遍历对象中的所有属性,我们需要用到循环,这里的for...in...循环和之前的for(...;...;...)循环形式不同,其形式如下:

for (key in object) {
  // 对此对象属性中的每个键执行的代码
}

例如:

let user = {
    name : "LiMing",
    age : 18,
    is_admin : false,
}

for (let key in user) {  // 在for循环中声明变量
    alert(key);  // name, age, is_admin

    alert(user[key])  // 使用 [ ] 取得值,为 LiMing, 18, false
}

如果键可以被转换为整数,则键会按照整数大小进行展示:

let codes = {
    "49" : "Germany",
    "48" : "USA",
    //...
    "1" : "China",
}

for (let code in codes) {
    alert( code );
    alert( codes[code] );
}

在这里展示的顺序并非是创建时的"49" : "Germany", "48" : "USA", ... , "1" : "China"

而是从1开始,即先是"1" : "China", ... , "48" : "USA", "49" : "Germany"

对象的存储

JS中,普通变量存储的是值本身。但对象不同,它存储的是对变量的引用,因此具有拷贝和克隆的性质。

可以使用Object.assign方法来进行克隆,其语法如下:

Object.assign(dest, [src1, src2, src3...])

其中,dest代表目标对象,src1, src2,...代表源对象,该方法可以将源对象中所有的属性克隆到目标对象中,并返回dest目标对象。

如果克隆的属性已经存在,则其会被覆盖:

let user = {
    name : 'LiMing',
}

Object.assign(user, {name : 'LiHua'});

alert(user.name);  // LiHua

但如果是嵌套对象,则还需要进行嵌套处理。

内存管理

JavaScript采用自动内存管理,只有当一个值不能经过任何有效途径访问,即值是不可达时,该内存才会被释放。类似图的可达性

14.1 对象方法

基本知识

从本质来说,对象的方法就是一个函数。

let user = {
    name : "LiMing",
}

user.say_hi = function () {  // 添加方法
    alert("Hello");
};

user.say_hi();  // Hello

/*
现在的user实际为

user = {
    name : "LiMing",
    sayhi : function () {
        alert("Hello");
        },
}

*/

也可以将预先声明的函数作为对象的方法:

let user = {
    name : "LiMing",
}

function say_hi() {  // 预先声明函数
    alert("Hello");
}

user.say_hi = say_hi;  // 将其添加为对象的方法

user.say_hi(); // Hello

也可以对方法进行简写:

let user = {
    say_hi() {   // 等价于say_hi : function () {  
    alert("Hello");
    },
}

user.say_hi(); // Hello

this

有时候,方法需要用到当前对象中的属性。比如,say_hi()方法就有可能调用user中的name属性。这时,就需要用到 this,它代表当前方法所指向的对象。

let user = {
    name : "LiMing",
    say_hi() {  
    alert(`Hello ${this.name}`);  
    },
}

user.say_hi(); // Hello LiMing

14.2 构造器和操作符"new"

在实际运用中,我们常需要构造同一类型的多个对象,比如构造多个用户。这时就需要用到构造器。

一般来说,构造函数有两个约定:

1. 一般以大写字母开头

2. 只能用 new 操作符执行

function User(name) {  // 构造器
    this.name = name;
    this.admin = false;
}

let user = new User("LiMing");  // 创建对象

alert( user.name );  // LiMing
alert( user.admin );  // false

构造器同样也可以创建方法:

function User(name) {  // 构造器
    this.name = name;
    this.admin = false;
    this.say_hi = function() {
        alert(`Hello ${this.name}`);
    };
}

let user = new User("LiMing");  // 创建对象

alert( user.name );  // LiMing
alert( user.admin );  // false
user.say_hi();  // Hello LiMing

14.3 可选链 ?.

在实际使用时,我们可能会遇见访问对象的属性不存在的情况,JS在默认情况下会返回一个错误,而使用可选链 ?. 可以帮助我们返回undefined或者null。其语法如下:value?.prop

  • 如果 value 存在,则结果与 value.prop 相同,
  • 否则(当 value 为 undefined/null 时)则返回 undefined

例如:

let user = {};

alert( user?.address );  // 返回undefined而不是报错

 如果 ?. 左边的部分不存在,则代码会停止执行并返回undefined,因此,该语句后的代码不会被执行。

let user = {};

function sayhi(x) {
    x++;
}

let x = 0;

user?.sayhi(x);  // 不会执行sayhi中的x++

alert( x );  // 0

变体 ?.() 和 ?.[]

同理 ?.() 可以用来调用一个可能不存在的方法:

let user_admin = {
    say_admin() {
        alert("I'm admin.");
    },
};

let user_guest = {};

user_admin.say_admin?.();  // I'm admin
user_guest.say_admin?.();  // undefined

?.[] 可以用来调用一个可能不存在的属性:

let user_admin = {
    password : '123456',
};
let user_guest = {};
let key = 'password';

alert( user_admin?.[key]);  // 123456
alert( user_guest?.[key]);  // undefined

14.4 Symbol类型

在JS中,对象的键只能是字符类型或Symbol类型。使用下面方法可以创建一个Symbol类型的变量:

let id = Symbol();  // id是Symbol的一个实例化对象

我们可以对Symbol类型的变量添加描述,这在调试代码时非常有用:

let id = Symbol("id");  // 以id为描述的名称为id的Symbol类型变量

Symbol类型的变量具有唯一性,即每个Symbol类型的变量都是不同的。

隐藏属性

使用Symbol可以隐式的添加属性,代码的其他部分都不能意外访问或重写此属性。

let user = {
    name : 'LiMing',
};

let id = Symbol("id");  // 创建Symbol类型的变量

user[id] = 1;  // 还记得[]的作用吗?

alert( user[id] );  // 1

如果要在创建对象时就引入Symbol类型的变量,应该使用 [id] 而非 "id",因为后者是字符类型:

let id = Symbol("id");  // 创建Symbol类型的变量

let user = {
    name : 'LiMing',
    [id] : 1,
};

Symbol类型的属性不会参与for...in...循环,但Object.assign可以克隆Symbol类型的属性。

全局Symbol

如果想在文件的不同地方访问到同一个Symbol实体,那就得使用Symbol.for(key)方法。

该方法会在全局注册表中查找一个描述为key的Symbol实体,如果该实体存在,则返回。如果不存在,则创建该实体并将其添加到全局注册表中。

let id2 = Symbol.for("id");  // 全局注册表中不存在描述为id的Symbol实体,则创建
let id3 = Symbol.for("id");  // 全局注册表中已存在描述为id的Symbol实体,则直接赋值

alert( id2 == id3 );  // true

Symbol.keyFor()方法可以通过Symbol变量名来找到对应的描述,这里的Symbol必须为全局Symbol:

let sym= Symbol.for("id");

alert( Symbol.keyFor(sym) );  // id

14.5 对象的原始值转换

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值