定义
前面我们通过学习html和css了解了如何设定网页的内容和样式,下面我们来学习JavaScript,它是控制网页行为的脚本语言(不能实现操作系统),可以说是前端三件套的核心,也是最难的部分。这篇文章我们来讲一些JS的基础知识。
与css类似,js也是写在html文件中的,可以写在body或者head标签中插入script标签;同时也可以创建外部的js文件(直接写js语句,无需script标签),然后在html的script标签的scr属性中链接js文件。
参考文献:JavaScript 教程 | 菜鸟教程 (runoob.com)
JS输出
有三种输出方式,分别是把内容写入HTML元素、写入HTML文档、写入浏览器的控制台
<body>
<h1>我的第一个网页</h1>
<p id="demo">这是一个段落</p>
<button onclick="myFunction()">点我</button>
<script>
// 写入元素
// 使用 document.getElementById(id) 方法访问元素
// 使用 innerHTML 属性设置或获取元素的内容
document.getElementById("demo").innerHTML = "这是一个新的段落";
// 写入文档
// 使用 document.write() 方法将向文档写入内容
// 注意:document.write() 方法只能在文档加载完成后才能执行,并且会覆盖整个页面
function myFunction() {
document.write(Date());
}
// 写到控制台
// 使用 console.log() 方法将内容输出到控制台
a = 5;
b = 10;
console.log(a + b);
</script>
</body>
JS事件
时间可以是浏览器行为也可以是用户行为,比如页面加载完成时、被点击时、页面关闭时,在事件触发时,js可以执行一些代码。可以用来处理表单验证,用户输入,用户行为和浏览器动作等。html元素中可以添加事件属性,使用js代码来添加js元素。比如:
<button onclick="getElementById('demo').innerHTML=Date()">现在的时间是?</button>
// 在按钮元素中添加了onclick属性
常见的html事件:
JS基本语法
数据类型
与其他编程语言相似,JS的数据类型有基本类型和对象类型,如数字、字符串、数组、对象等等。
- 基本类型:字符串、数组、布尔、未定义(undefined)
- 对象类型:对象、数组、函数、正则、日期、空
实际上js的变量都是对象,声明一个变量的时候,就创建了一个新的对象。所以在变量的初始化上,js数据类型没有分得那么细,不像C语言还要写明具体是哪种类型,有点像python,管他是什么类型直接初始化就完了,初始化变量的关键字是
var
,无值的变量的值实际是未定义undefined
,如果数组越界访问也会显示undefined;如果一个有值的变量被重新声明,该变量的值不会丢失。
而且呢,js拥有动态类型,这意味着相同的变量可以用作不同的类型,变量的数据类型可以通过typeof
操作符来查看
var length = 16; // Number 通过数字字面量赋值
var points = x * 10; // Number 通过表达式字面量赋值
var lastName = "Johnson"; // String 通过字符串字面量赋值
var cars = ["Saab", "Volvo", "BMW"]; // Array 通过数组字面量赋值
var person = {firstName:"John", lastName:"Doe"}; // Object 通过对象字面量赋值
var x; // x 为 undefinedvar
x = 5; // 现在 x 为数字
var x = "John"; // 现在 x 为字符串
typeof "John" // 返回 string
typeof 3.14 // 返回 number
typeof false // 返回 boolean
typeof [1,2,3,4] // 返回 object
typeof {name:'John', age:34} // 返回 object
函数
函数也是一种对象类型,可以声明时赋值给变量,也可以单独自己赋值
// 可以这样写
var myFunction = function(a, b) {
return a * b; // 返回 a 乘以 b 的结果
}
// 也可以这样写
function myFunction(a, b) {
return a * b; // 返回 a 乘以 b 的结果
}
document.getElementById("demo").innerHTML=myFunction(4,3); // 函数调用
js是脚本语言,浏览器在读取代码时,会逐行地执行脚本代码,执行到return代表函数结束返回结果,如果没有执行到return,函数执行完会返回undefined。而对于传统编程来说,会在执行前对所有代码进行编译。
js有一个自带的参数argument
,把传递给函数的参数转换成一个类数组,它有长度属性但没有数组的内置方法,比如forEach()
function func1(a, b, c) {
console.log(arguments[0]);
// Expected output: 1
console.log(arguments[1]);
// Expected output: 2
console.log(arguments[2]);
// Expected output: 3
}
func1(1, 2, 3); // Output: 1 2 3
但是在es6中,出现了一个更好用的剩余参数,也就是...参数
,如果函数的最后一个命名参数以...为前缀,就可以将传给函数的剩余的参数转换为一个数组,对应着没有形参的实参,同时也可以被解构。与argument不同的是,argument包含了传给函数的所有实参,而且剩余参数是真正的数组,可以使用数组的方法。
function sum(a, ...theArgs) { //theArgs包含了除了第一个参数外的其他参数
let total = 0;
for (const arg of theArgs) {
total += arg;
}
return total;
}
console.log(sum(1, 2, 3)); // 5
console.log(sum(1, 2, 3, 4)); // 9
函数放到对象里就是方法,用法和java基本一致。有一个以前没见过的关键词是apply,用来调用函数。apply(thisArg, argsArray)
,第一个参数指定调用时的this参数,第二个参数用来指定调用时的参数
// 定义一个函数
function getAge(){
var now = new Date().getFullYear();
return now = this.birth;
}
// 定义一个对象
var xiaoming = {
name: "小明",
birth: 1990,
age: getAge
}
getAge.apply(xiaoming, []); // this指向xiaoming,参数为空
对象
js的对象是变量(键值对)的容器,所有的键都是字符串,值是任意对象。有属性和方法。
属性通常用键值对的方法呈现:name : value
,有两种访问方式。如果访问不存在的属性,会显示undefined,动态删减属性用delete
关键字,动态添加属性直接添加就好。如果要判断某个属性值是否在这个对象中,使用xxx in xxx
。
创建方法的语法methodName : function(){// 代码}
;访问方法也有两种方式,一种是访问方法,一种会返回函数的定义
var person = { // 初始化对象
firstName: "John",
lastName : "Doe",
id : 5566,
methodName : function(){ // 创建方法
return this.firstName + " " + this.lastName;
}
};
person.lastName; //访问对象属性
person["lastName"]; //访问对象属性
person.name = 'haha' //添加属性
delete persion.name; //删除属性
'name' in person; //返回false
//通常methodName()是作为person对象的一个方法,methodName是作为一个属性。
objectName.methodName(); //函数属性作为方法访问
objectName.methodName; //函数属性作为属性访问
数组
js中的数组与其他语言类似,有一些属性和方法,比如长度length
,在末尾添加元素push()
,弹出末尾元素pop()
,在开头添加元素unshift()
,弹出开头元素shift()
,排序sort()
,元素反转reverse()
,截取数组的一部分slice()
(类似string中的substring),拼接并返回新数组concat()
,使用特定连接符拼接并打印数组join()
等等,有需要的时候可以去查看文档。
如果设置数组的length,会改变数组的长度,自动填充undefined或者砍掉多出的部分;如果访问数组时越界了,会报undefined。
var myArr =[1,2,3,4,5];
console.log(myArr); //打印数组 [1, 2, 3, 4, 5]
console.log(myArr.length); //获取数组长度 5
console.log(myArr[0]); //获取数组第一个元素 1
console.log(myArr[1]); //获取数组第二个元素 2
myArr.push(6); //添加元素到数组末尾
myArr.unshift(0); //添加元素到数组开头
console.log(myArr); // [0, 1, 2, 3, 4, 5, 6]
myArr.pop(); //删除数组末尾元素
myArr.shift(); //删除数组开头元素
console.log(myArr); // [1, 2, 3, 4, 5]
有时会遇到数组遍历,在js中有一个快捷方法来简化for循环的过程,也就是forEach(function(item))
var arr = [1, 2, 3, 4, 5];
arr.forEach(function (item) {
if (item === 3) {
return;
}
console.log(item);
});
作用域与生命周期
与其他编程语言类似,变量如果在函数内部声明,则为局部变量,具有局部作用域,在函数运行后被删除;如果在函数外定义,则为全局变量,具有全局作用域,网页中所有函数和脚本都可用,在页面关闭后被删除。
有一种特殊情况,如果没有使用var关键字,也就是赋值给未声明的变量,则该变量自动编程绑定到windows上的全局变量,可以全局使用,在函数中也一样,可以使用delete
关键字删除。
js只有一个全局作用域,任何变量如果没有在函数作用范围内找到,就会向外查找,如果在全局作用域都没有找到,就会报错。如果定义了重名的全局变量,可能会导致全局命名冲突。有个好的编码习惯:把自己的代码全部放入自己定义的唯一空间中,可以有效避免上述问题。
另外,js会自动提升变量的声明,但不会提升变量的赋值。如果在赋值之前就使用变量会显示undefined。在写代码时最好养成规范,所有的变量定义都放在函数的头部,便于维护。
字符串
js的字符串是一种对象变量,有一些常用的属性和方法,这里截取了一部分
需要注意的是,如果想在字符串中添加引号,需要加转义字符\
,如果想拼接两个字符串,请使用+
运算符
与其他语言不同的是,js还有一种字符串叫模板字符串,是一种方便的字符串语法,允许在字符串中嵌入表达式和变量,与普通字符串不同,模板字符串是用反引号括起来的``,允许多行字符串,带嵌入表达式的字符串插值(用美元符号和大括号括起来
${expression}
。普通的引号无需转义字符就可以在模板字符串中使用,但是反引号就需要加转义字符
const name = 'John';
const age = 31;
const job = 'Web Developer';
const city = 'Beijing';
function hello(){
return 'hello';
}
let str =`
Name:${name}
age:${age}
job:${job}
city:${city}
calc:${2+2}
function:${hello()}
sanmu: ${age >
30 ? 'over 30': 'under 30' }
`
console.log(str);
运算符
与其他编程语言也是大同小异啦,唯一有些不同的就是js有绝对等于(值和类型均相等)===
和绝对不等于(值和类型有一个不相等或两个都不相等)!==
类型转换
有很多种类型转换呀,不赘述了,有需要的时候翻菜鸟教程吧
JavaScript 类型转换 | 菜鸟教程 (runoob.com)
调试
既然要写代码就必然会出bug,这时候就需要调试,如何调试呢?
我在参照了edge浏览器的调试教程,总结了大概以下几个步骤:
- 按f12调出检查模式
- 按源代码栏,在右侧点击事件监听器断点,浏览器就可以在进行某个操作时暂停
- 添加断点,调试,在作用域里查看变量,修改代码
- 最后按ctrl+s保存代码