当前位置: 首页 > news >正文

JavaScript的初步学习

JavaScript简介

JavaScript(简称JS)是一种广泛使用的动态脚本语言,主要用于网页开发,赋予网页动态交互功能。它由网景公司(Netscape)的布兰登·艾奇(Brendan Eich)在1995年开发,最初名为LiveScript,后来改名为JavaScript。


主要特点

  • 客户端脚本:主要在浏览器中执行,使网页具有动态效果和交互能力(如表单验证、动画、实时更新内容等)。

  • 动态类型:变量类型在运行时确定,不需要预定义。

  • 弱类型:类型转换自动进行,使用灵活。

  • 事件驱动:响应用户操作(点击、悬停、提交等)。

  • 多范式:支持面向对象、函数式、命令式编程。


主要用途

  • 网页交互:实现按钮点击、表单验证、动画效果。

  • 网页开发框架:如React、Vue、Angular。

  • 服务器端编程:通过Node.js,JavaScript还能在服务器执行。

  • 移动应用:如React Native。

  • 桌面应用、游戏开发:通过特殊平台和引擎实现。


JavaScript的基本特性

  • 简洁灵活的语法:类似C、Java的语法,但比它们简单易用。

  • 原生支持事件处理:可以直接在HTML或JavaScript中绑定事件。

  • DOM操作:可以直接操作网页结构(Document Object Model)。

  • 异步编程:支持Promise、async/await等技术,方便处理异步任务。

 JavaScript的引入方式

1. 内联方式 (Inline JavaScript)

概念: 将JavaScript代码直接作为HTML标签的属性值使用。通常用于处理特定的事件,例如点击按钮时执行一段JS代码。

优点:

  • 简单直接,适用于非常短小、针对特定元素的逻辑。

  • 无需额外的文件或<script>标签。

缺点:

  • 极其不推荐! 严重违反了结构(HTML)、样式(CSS)、行为(JavaScript)分离的原则。

  • 代码可读性差,难以维护。

  • 代码复用性差。

  • 增加了HTML文件的体积。

<!DOCTYPE html>
<html>
<head><title>内联JavaScript示例</title>
</head>
<body><button onclick="alert('你点击了我,内联方式!');">点击我</button><a href="#" onmouseover="this.style.color='red';"onmouseout="this.style.color='black';">鼠标悬停</a>
</body>
</html>

2. 内部方式 (Internal JavaScript / Embedded JavaScript)

概念: 将JavaScript代码放置在HTML文件的<script>标签内部。<script>标签可以放在HTML文档的<head>部分,也可以放在<body>部分。

优点:

  • 代码都在一个HTML文件中,方便小型项目或单页面应用。

  • 避免了额外的HTTP请求。

缺点:

  • 不利于代码复用。如果多个HTML页面需要相同的JavaScript代码,就需要复制代码。

  • 增加了HTML文件的体积,下载时需要加载整个JS代码。

  • 如果JS代码量很大,可能会阻塞页面内容的渲染(尤其是放在<head>里)。

建议放置位置: 通常推荐将 <script> 标签放置在 <body> 标签的闭合标签 </body> 之前。这样做的原因是:

  • 避免阻塞渲染: 浏览器在解析HTML时,遇到 <script> 标签会暂停HTML的解析和渲染,转而去下载和执行JavaScript代码。如果JavaScript在页面的顶部(<head>中)且代码量较大,用户可能会看到空白页面的时间延长。

  • 确保DOM可用: JavaScript代码通常需要操作HTML元素(DOM)。如果JavaScript在元素加载之前就执行,可能会找不到要操作的元素,导致错误。将JavaScript放置在 </body> 之前,可以保证它执行时,页面上的所有HTML元素已经被浏览器解析并创建为DOM树。

<!DOCTYPE html>
<html lang="zh-CN">
<!-- HTML文档的语言设置为中文 -->
<head><!-- 字符集为UTF-8 --><meta charset="UTF-8"><!-- 设置浏览器兼容性 --><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>内部JavaScript示例</title><script>// 这是放置在 head 标签内的 JavaScript 代码function showHeadMessage() {console.log("这是来自 head 标签内的 JavaScript。");}</script>
</head>
<body><h1>内部JavaScript</h1><p id="myParagraph">这是一个段落。</p><button onclick="changeText()">点击改变段落</button><script>// 这是放置在 body 标签末尾的 JavaScript 代码function changeText() {document.getElementById("myParagraph").innerText = "段落内容已被JavaScript改变!";}// 页面加载完成后执行window.onload = function() {showHeadMessage(); // 调用 head 中的函数console.log("页面已加载完成,这是来自 body 标签末尾的 JavaScript。");};</script>
</body>
</html>

3. 外部方式 (External JavaScript)

概念: 将JavaScript代码单独保存在一个.js文件中,然后在HTML文件中通过<script>标签的 src 属性引入。

优点:

  • 最推荐的方式! 实现了结构、样式、行为的完全分离,代码清晰,易于维护。

  • 代码复用性高: 多个HTML页面可以引用同一个.js文件,避免重复编写代码。

  • 浏览器缓存: .js文件可以被浏览器缓存,当用户再次访问或访问其他页面时,无需重新下载,加快页面加载速度。

  • 优化加载性能:

    • 可以使用 defer 属性:脚本会延迟到文档解析完成后才执行,但会按照它们在文档中出现的顺序执行。不会阻塞HTML解析。

    • 可以使用 async 属性:脚本会异步加载,并在加载完成后立即执行,不保证执行顺序,也会阻塞HTML解析(但只在脚本下载期间)。

    • 推荐:将 <script> 标签放在 </body> 闭合标签之前。

缺点:

  • 增加了一个HTTP请求(但可以通过浏览器缓存弥补)。

// script.js
function sayHello() {alert("你好,这是来自外部JavaScript文件!");
}
function updateDiv() {document.getElementById("messageDiv").innerText = "外部JS已修改此内容。";
}
// 页面加载完成后执行
window.onload = function() {console.log("外部JavaScript文件已加载并执行。");
};
<!DOCTYPE html>
<html lang="zh-CN">
<head><!-- 字符集为UTF-8 --><meta charset="UTF-8"><!-- 设置浏览器兼容性 --><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>外部JavaScript示例</title><!-- 推荐使用 defer 或放在 body 底部 --><script src="script.js" defer></script>
</head>
<body><h1>外部JavaScript</h1><p>这是来自HTML页面的内容。</p><div id="messageDiv">原始内容</div><button onclick="sayHello()">点击问候</button><button onclick="updateDiv()">更新内容</button>
</body>
</html>

JavaScript的语法介绍

1.书写语法

 2.输出语句

3.变量

 (1)变量的声明关键词

JavaScript中声明变量主要使用三种关键词:varletconst。这三者在作用域、可变性等方面存在差异。

a. var
  • 最早的变量声明方式。

  • 作用域为函数作用域(函数内部有效,函数外面不可见);

  • 可以重复声明同一变量,后声明会覆盖前面。

b. let
  • ES6(ECMAScript 2015)引入。

  • 作用域为块作用域(比如在ifforwhile块内有效);

  • 不允许重复声明同一变量。

c. const
  • 也是ES6引入。

  • 作用域为块作用域

  • 必须初始化,声明后不可再赋值;

  • 对于对象和数组,虽然引用不可变,但对象内容还是可变的。

(2) 变量的命名规则

  • 只能以字母、$_开头;

  • 后续可以使用字母、数字、$_

  • 不能使用JavaScript关键字(如ifvarfunction等)作为变量名;

  • 推荐命名具有描述性(语义清晰)。

(3) 变量的作用域

  • var声明的变量:函数作用域或全局作用域(如果在函数外部声明)

  • letconst声明的变量:块作用域(例如在ifforwhile内有效)

(4) 变量的提升(Hoisting)

  • var声明的变量会提升:变量声明会被提升到作用域顶部,但赋值不会。

  • letconst不会提升,会在块内形成“暂时性死区(TDZ)”,访问会报错。

console.log(x); // undefined,因为var会提升声明
var x = 5;console.log(y); // 报错:Cannot access 'y' before initialization
let y = 10;console.log(z); // 报错:Cannot access 'z' before initialization
const z = 15;

 4.数据类型

(1)基本数据类型(原始类型)

a. 数字(Number)
  • 表示整数和浮点数。

  • JavaScript中的数字采用双精度浮点(IEEE 754标准)。

  • 特殊值:Infinity-InfinityNaN(非数字)

let integerNum = 42;           // 整数
let floatNum = 3.1415;         // 浮点数
let infinity = Infinity;       // 正无穷
let nanValue = NaN;              // 非数字

 注意:NaN表示“非数值”,且NaN本身不等于任何值,包括自己。

console.log(NaN === NaN); // false
console.log(isNaN(NaN));   // true
b. 字符串(String)
  • 用单引号''或双引号""(也支持反引号 ``)表示。

  • 支持转义字符和模板字符串。

let str1 = 'Hello';
let str2 = "World";
let str3 = `Hello, ${str2}!`; // 模板字符串,支持插值
c. 布尔值(Boolean)
  • 只有两个值:true 和 false

d. undefined
  • 表示变量未定义或未赋值。

e. null
  • 表示“空值”,需要显式赋值。

f. Symbol(符号)
  • 在ES6引入。

  • 用于创建唯一的标识符。

const sym1 = Symbol('foo');
const sym2 = Symbol('foo');
console.log(sym1 === sym2); // false,符号唯一

(2)复杂数据类型(引用类型)

a. 对象(Object)
  • 键值对集合,属性名为字符串(或Symbol),值可以为任何类型。

  • 字面量定义

let obj = {name: 'Alice',age: 25,greet: function() { return 'Hello'; }
};
b. 数组(Array)
  • 数对象的特殊类型,存储有序元素。

let arr = [1, 2, 3, 'a', true];
c. 特殊对象:DateRegExpError
let dateNow = new Date();
let regex = /ab+c/;

(3)类型转换

JavaScript会在需要时自动进行类型转换(隐式转换),也可以手动转换。

a. 转字符串
String(123);       // '123'
(123).toString();  // '123'
b. 转数字
Number('456');     // 456
parseInt('123', 10);  // 123
parseFloat('3.14');   // 3.14
parseInt('12abc');   //12
parseInt('abc');   //NaN
 c. 转布尔值
Boolean(0);       // false
Boolean('');      // false
Boolean('hello'); // true
Boolean(undefined); // false

注意: 以下值在转换为布尔值时为false,称为“假值”或“false值”:

  • false

  • 0

  • -0

  • 0n(BigInt零)

  • null

  • undefined

  • NaN

  • 空字符串 ''

其他值为真(true)。

(4)值得注意的细节

a. typeof运算符

用来判断变量的数据类型。

typeof 123;             // 'number'
typeof 'hello';         // 'string'
typeof true;            // 'boolean'
typeof undefined;       // 'undefined'
typeof null;            // 'object'(这是一个历史遗留问题,null实际上是原始类型)
typeof Symbol('foo');     // 'symbol'
typeof {a:1};           // 'object'
typeof [1,2,3];         // 'object'(数组也是对象)
typeof function(){};    // 'function'(函数也是对象的一种)

b.instanceof

判断对象是否是某个类的实例。

let arr = [1,2,3];
console.log(arr instanceof Array); // true
console.log({} instanceof Object); // true

5.运算符

 6.流程控制语句

和Java相近。

 

7.函数

(1) 函数的定义方式

a.函数声明(Function Declaration)
function 函数名(参数列表) {// 函数体
}

特点:

  • 函数会被提升(hoisted),可以在声明之前调用。

  • 适合定义在代码顶层或块内的标准函数。

b.函数表达式(Function Expression) 
const func = function(参数) {// 函数体
};

特点:

  • 不会被提升,只能在声明后使用。

  • 通常用作回调函数。

c.箭头函数(Arrow Function) 
const func = (参数) => {// 函数体
};

特点:

  • 语法简洁,尤其适合写短函数。

  • 不绑定自己的this,常用于回调或匿名函数。

(2)函数参数的语法和细节

a. 默认参数(Default Parameters)
function greet(name='Guest') {console.log('Hello, ' + name);
}
greet(); // 'Hello, Guest'
b. 剩余参数(Rest Parameters)

收集多余参数为数组:

function sum(...numbers) {return numbers.reduce((acc, curr) => acc + curr, 0);
}
console.log(sum(1, 2, 3, 4)); // 10
c. 参数解构(Destructuring)

解构数组或对象参数:

function display({name, age}) {console.log(name, age);
}
display({name: 'Alice', age: 30});

(3) 函数作用域与闭包

a. 作用域
  • 函数定义的变量在函数内部有效,外部不可访问(除非返回或传递)。

  • 函数内部可以访问外部作用域。

b. 闭包
  • 函数配合其定义环境形成闭包,能“记住”当时的作用域。

function outer() {let count = 0;return function inner() {count++;console.log(count);}
}
const increment = outer();
increment(); // 1
increment(); // 2

(4)函数的this绑定规律

a. 普通函数
  • 在严格模式('use strict')下,thisundefined

  • 在非严格模式下,this指向全局对象(浏览器window)。

function show() {console.log(this);
}
show(); // 在非严格模式:window;严格模式下:undefined
b. 箭头函数
  • 没有自己的this,继承自定义声明时所在的作用域。

const obj = {value: 42,getValue: function() {const arrowFunc = () => this.value;return arrowFunc();}
};
console.log(obj.getValue()); // 42
c. 更复杂的绑定规则
  • 使用callapplybind可以强制指定this

const obj = {name: 'Bob'};
function showName() {console.log(this.name);
}
showName.call(obj); // 'Bob'

(5)函数的返回值

  • 默认返回undefined

  • 使用return语句返回值。

  • 函数可以返回任何类型的数据。

注意:

  • 一旦遇到return,函数立即结束。

  • 可以返回对象、数组、函数等。

(6) 生成器函数(Generator Functions)

  • 使用function*定义。

  • 产生可迭代的值。

function* gen() {yield 1;yield 2;yield 3;
}
const iterator = gen();
console.log(iterator.next()); // { value: 1, done: false }

 8.对象

(1)常用对象

 

 

 (2)自定义对象

在JavaScript中,对象是键值对的无序集合。键(key)是字符串(或Symbol),值(value)可以是任何数据类型(包括原始类型、其他对象、函数等)。

a. 对象的创建方式
 对象字面量(Object Literal)- 最常用

这是创建对象最简单、最常用的方式。

// 语法:
let objectName = {key1: value1,key2: value2,// ...
};// 示例:
let person = {name: "Alice",        // 属性(property)age: 30,              // 属性isStudent: false,     // 属性greet: function() {   // 方法(method)console.log("Hello, my name is " + this.name);}
};

细节:

  • 属性名可以是标识符(不带引号,如name),也可以是字符串(带引号,如"user-id")。如果属性名是无效的标识符(如包含连字符、空格或数字开头),则必须用引号。

  • 属性值可以是任何数据类型。

  • 方法是值为函数的属性。

  • this关键字在对象方法中指向当前对象本身。

new Object() 构造函数

不常用,但也是一种创建方式。

let person = new Object();
person.name = "Bob";
person.age = 25;
person.greet = function() {console.log("Hi, I'm " + this.name);
};
构造函数(Constructor Function)- 创造类实例的“模板”

用于创建具有相同属性和方法的多个对象。

// 语法:
function ConstructorName(param1, param2) {this.property1 = param1;this.property2 = param2;this.method = function() {// ...};
}// 示例:
function Person(name, age) {this.name = name;this.age = age;this.greet = function() {console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");};
}// 使用 new 关键字创建实例
let person1 = new Person("Charlie", 40);
let person2 = new Person("Diana", 28);person1.greet(); // Hello, my name is Charlie and I am 40 years old.
person2.greet(); // Hello, my name is Diana and I am 28 years old.

细节:

  • 函数名通常首字母大写(约定)。

  • this关键字在构造函数中指代新创建的实例。

  • 必须使用new关键字来调用构造函数,否则this会指向全局对象(非严格模式下)。

  • 每个实例都会有自己的greet方法,这可能会造成内存浪费(因为方法相同)。

使用原型(Prototype)优化构造函数 - 共享方法

为了避免每个实例都拥有独立的方法副本,可以将方法定义在构造函数的原型上。

function Person(name, age) {this.name = name;this.age = age;
}// 将方法添加到 Person.prototype
Person.prototype.greet = function() {console.log("Hello, my name is " + this.name + " and I am " + this.age + " years old.");
};let person3 = new Person("Eve", 35);
person3.greet(); // Hello, my name is Eve and I am 35 years old.

细节:

  • Person.prototype是一个对象,所有由Person构造函数创建的实例都会通过原型链继承Person.prototype上的属性和方法。

  • greet方法现在只存在一份,被所有Person实例共享,节约内存。

ES6 class 语法 - 现代JS推荐的面向对象方式

class是JavaScript中用来创建对象的语法糖,底层依然是原型和构造函数。

class Person {constructor(name, age) {this.name = name;this.age = age;}greet() { // 方法直接定义在类内部,会被添加到原型上console.log(`Hello, my name is ${this.name} and I am ${this.age} years old.`);}// 静态方法(属于类本身,不属于实例)static sayHello() {console.log("Hello from the Person class!");}
}let person4 = new Person("Frank", 50);
person4.greet(); // Hello, my name is Frank and I am 50 years old.
Person.sayHello(); // Hello from the Person class!

细节:

  • constructor方法是类默认的构造函数,当使用new关键字创建实例时,会自动调用它。

  • constructor之外定义的方法会自动添加到原型上。

  • static关键字用于定义静态方法,只能通过类本身调用,不能通过实例调用。

b. 访问和修改对象属性/方法
点表示法(Dot Notation)
console.log(person.name); // Alice
person.age = 31;
person.greet();
方括号表示法(Bracket Notation)

当属性名包含特殊字符、空格、或是一个变量时,必须使用方括号表示法。

console.log(person["name"]); // Alicelet propName = "age";
console.log(person[propName]); // 31person["favorite-color"] = "blue"; // 可以添加带连字符的属性
console.log(person["favorite-color"]);
c. 删除对象属性

使用delete运算符。

delete person.isStudent;
console.log(person.isStudent); // undefined
d. 检查属性是否存在
in 运算符

检查属性是否在对象或其原型链上。

console.log("name" in person);        // true
console.log("toString" in person);    // true (继承自Object.prototype)
console.log("job" in person);         // false
hasOwnProperty() 方法

检查属性是否是对象自身的属性(非继承)。

console.log(person.hasOwnProperty("name"));       // true
console.log(person.hasOwnProperty("toString"));   // false
e. 遍历对象属性
for...in 循环

遍历对象可枚举的属性(包括原型链上的)。

for (let key in person) {console.log(`${key}: ${person[key]}`);
}
// 注意:for...in 会遍历原型链上的可枚举属性,需要结合 hasOwnProperty() 筛选
for (let key in person) {if (person.hasOwnProperty(key)) {console.log(`Own property - ${key}: ${person[key]}`);}
}
Object.keys()

返回一个包含对象自身所有可枚举属性名的数组。

let keys = Object.keys(person);
console.log(keys); // ['name', 'age', 'greet', 'favorite-color']keys.forEach(key => {console.log(`${key}: ${person[key]}`);
});
Object.values()

返回一个包含对象自身所有可枚举属性值的数组。

let values = Object.values(person);
console.log(values); // ['Alice', 31, Function, 'blue']
Object.entries()

返回一个包含对象自身所有可枚举属性的[key, value]对数组。

let entries = Object.entries(person);
console.log(entries); // [['name', 'Alice'], ['age', 31], ['greet', Function], ['favorite-color', 'blue']]for (let [key, value] of entries) {console.log(`${key}: ${value}`);
}

f. 短属性名和短方法名(ES6)

当变量名和属性名相同时,可以简写。

let myName = "Grace";
let myAge = 22;let user = {myName,    // 等同于 myName: myNamemyAge,     // 等同于 myAge: myAgewalk() {   // 等同于 walk: function() { ... }console.log("Walking...");}
};
console.log(user.myName); // Grace
user.walk(); // Walking...

g. 计算属性名(Computed Property Names)(ES6)

属性名可以是一个表达式的结果。

let prop = "dynamicKey";
let obj = {[prop + "1"]: "value1",['another' + 'Key']: "value2"
};
console.log(obj.dynamicKey1);  // value1
console.log(obj.anotherKey);   // value2

9.JSON

(1)什么是JSON

  • JSON(JavaScript Object Notation)是一种轻量级的数据交换格式,易于读写和解析。

  • 它是基于JavaScript对象字面量语法的文本格式,但不仅限于JavaScript,可以在多种编程语言中使用。

(2)JSON的语法规则

a.基本结构
  • 数据是键值对的集合

  • 可以是对象(用{}包围)或数组(用[]包围)

b.JSON对象(Object)
{"key1": value1,"key2": value2,...
}
c. JSON数组(Array)
[value1,value2,...
]
d. 数值(Number)
  • 支持整数和浮点数

e. 字符串(String)
  • 必须用双引号(")包围

  • 支持转义字符(如\n\t\"\\

f. 布尔值(Boolean)
g. null值 
h. 不能出现
  • 单引号(字符串必须双引号)

  • 函数、日期对象、undefined(这些在JSON中不被支持)

  • 不能有函数作为值

{"name": "John","age": 25,"isStudent": false,"scores": [95, 82, 88],"address": {"city": "New York","zip": "10001"},"skills": null
}

(3)在JavaScript中操作JSON

a.转换为JSON字符串:JSON.stringify

将JavaScript对象转成JSON字符串(常用于数据传输或存储)

const obj = { name: "Alice", age: 30 };
const jsonStr = JSON.stringify(obj);
console.log(jsonStr); // '{"name":"Alice","age":30}'
b. 解析JSON字符串:JSON.parse

将JSON字符串转成JavaScript对象(常用于接收数据)

const jsonStr = '{"name":"Bob","age":25}';
const obj = JSON.parse(jsonStr);
console.log(obj.name); // "Bob"

(4)扩展:自定义对象转JSON的细节

当调用JSON.stringify()时,可以传入replacer参数,用于控制序列化过程。

const obj = {name: "Tom",age: 28,greet() { return "Hi"; }
};
console.log(JSON.stringify(obj)); // 无`greet`方法,输出:{"name":"Tom","age":28}// 只序列化特定字段
JSON.stringify(obj, ['name', 'age']);// 美化输出,添加空格缩进
JSON.stringify(obj, null, 2);
  • 注意:除数据外,函数和符号会被忽略。

http://www.lryc.cn/news/579522.html

相关文章:

  • 2021/7 N2 jlpt 词汇
  • npm ERR! code ERESOLVE npm ERR! ERESOLVE unable to resolve dependency tree
  • Apache POI 详解 - Java 操作 Excel/Word/PPT
  • docker-compose一键部署全栈项目。springboot后端,react前端
  • 如何将信息从 iPhone 同步到Mac(完整步骤和示意图)
  • mac 电脑安装Homebrew来安装npm与node成功后,安装nvm的流程
  • MySQL 8.0 OCP 1Z0-908 题目解析(19)
  • 标准测试测试数据STDF学习笔记
  • MediaCrawler:强大的自媒体平台爬虫工具
  • Spring Boot 多 ActiveMQ 通道配置与多连接消息发送实战(含完整示例与踩坑记录)
  • Ubuntu 24.04 LTS 服务器配置:安装 JDK、Nginx、Redis。
  • 一体机电脑为何热度持续上升?消费者更看重哪些功能?
  • 关于系统无法找到 arm-linux-gcc 命令,这表明你的环境中尚未安装 ARM 交叉编译工具链。以下是详细的解决方案:(DIY机器人工房)
  • 牛客:HJ16 购物单【01背包】【华为机考】
  • 封装 获取paramsByKey 方法
  • 毕业设计(启智模块化机器人的组装与K5的使用
  • 使用Visual Studio 2022创建CUDA编程项目
  • 车载交换机动态MAC学习和静态MAC绑定如何获取MAC地址表
  • jenkins角色权限
  • 这才叫窗口查询!TDEngine官方文档没讲透的实战玩法
  • 微信小程序41~50
  • 佰力博科技与您探讨压电材料的原理与压电效应的应用
  • C++(std::sort)
  • 【轨物洞见】光伏机器人与组件、支架智能化协同白皮书
  • 如何避免服务器出现故障情况?
  • SPLADE 在稀疏向量搜索中的原理与应用详解
  • 【NLP入门系列四】评论文本分类入门案例
  • ubuntu 6.8.0 安装xenomai3.3
  • lspci查看PCI设备详细信息
  • OpenCV篇——项目(二)OCR文档扫描