JavaScript简介
JavaScript最初只是为了进行前端页面开发,后面有了更多的功能:开发桌面程序、手机app、服务器端的程序等。
JS是运行在浏览器上的,比如chrome里面专门有一个模块,就是JS引擎,相当于JVM一样,能够解释执行JS代码,后面把这部分代码单独拿出来,封装成独立的程序,称为V8引擎。
JavaScript组成
JavaScript组成
- ECMAScript(ES):JavaScript语法
- DOM:页面文档对象模型,DOM API 是浏览器给js提供的操作页面元素的API
- BOM:浏览器对象模型,BOM 是浏览器给js提供的另一组操作浏览器窗口的API
主要学习ES部分和DOM中常用API
浏览器加载html就会从上到下的依次执行每个script标签里的代码
JavaScript引入方式
- 内部JS:写到script标签中
<script>
alert('hello');
</script>
- 外部JS:写成单独的 .js 文件,让 html 引入过来
<script src="add.js"></script>
- 行内JS:直接写到 html 元素内部
<div onclick="alert('hello')">这是一个div,点我一下</div>
alert能够弹框,从而让用户看到程序的输出,但是弹框操作不太好。有些对话框一弹出来就会阻止用户操作界面的其他部分,叫做模态对话框。
更推荐使用console.log 就可以在控制台中打印日志。js里的console.log就类似于java中的println ,是有用的调试手段
JavaScript 变量
js定义变量不写类型,不写类型不意味"没有类型"。变量的类型通过初始化操作的值来确定。
JS不区分int和double,统一都叫做number类型。
var 变量名 = 初始值;
js里定义变量使用的关键字还可以是写作let【推荐】
var是属于老式写法,let是新式写法,规则更接近C++ Java等主流语言
let 变量名 = 初始值;
JS动态类型
let a = 10;
console.log(a);
a = 'hello';
console.log(a);
一个变量在程序运行过程中,类型可以发生改变。 动态类型:JS、Python、PHP、Lua…
一个变量在程序运行过程中,类型不能发生改变。 静态类型:C 、Java、C++、Go…
动态类型的好处是代码非常灵活。
比如,写一个函数,计算两个数字的和,如果使用Java,要写个两个int相加的版本、写个两个double相加的版本、写个两个long相加的版本…
而动态类型的语言,只需要写一个函数即可。
动态类型的坏处:一个变量当下到底是啥类型,里面存了啥样的值,里面提供了哪些方法哪些属都是不确定的。
JS中内置的几种类型
- number:数字。不区分整数和小数
- boolean: true真,false假
- string: 字符串类型
- undefined: 只有唯一的值undefined。表示未定义的值.
- null: 只有唯一的值null。表示空值.
在别的语言中,如果访问到某个没有定义的东西,直接报错。JS不报错,而是返回个undefined。
JS把别的语言认为非法的行为合法化。
隐式类型转换
这个代码中触发了“隐式类型转换’。JS针对不相同的类型进行比较/运算,会尝试尽可能的转成相同类型
let a = 10;
let b = '10';
console.log(a == b); /* true */
let c = true
let d = 1;
console.log(c == d); /* true */
let e = 2;
console.log(c == e); /* false */
像Java这种,不太支持隐式类型转换的语言,称为"强类型"语言。
像JS这种,比较能支持隐式类型转换的语言,称为"弱类型"语言。
业界共识:强类型比弱类型好。类型强,相当于不同类型之间的区分度就高。编译器能做的检查工作就更多,代码出错的概率就降低了。
===
比较相等:不会进行隐式类型转换
js 数组
let arr = new Array(); /* 很少这么写 */
let arr2 = []; /* */
let arr3 = [1, 2, 3, 4];
JS中,数组的元素类型不要求统一,可以是任意类型。不仅仅js如此,动态类型的语言都是如此。
let arr3 = [1, 'hello', true, []];
站在C语言的视角,每个js中的变量(对象)都有一个地址(唯一身份标识)。
数组说是存储元素,其实是存的对应的身份标识。身份标识都是统一格式的内容。在底层用一个C的数组来存储这些身份标识,在上层js这里就相当于是保存不同对象了。
操作数组元素:访问下标。
let arr4 = ['a', 'b', 'c'];
console.log(arr4[0]);
console.log(arr4[1]);
console.log(arr4[2]);
访问越界的数组下标,程序依然执行,返回undefined。
JS的数组,不仅仅是一个传统意义的,只能按下标来取元素的数组
而是一个带有"键值对"性质的东西。不如理解成,数组+ Map的混血。
let arr4 = ['a', 'b', 'c'];
arr4['hello'] = 'aa';
console.log(arr4);
数组遍历
let arr4 = ['a', 'b', 'c'];
for(let i = 0; i < arr4.length; i++) {
console.log(arr4[i]);
}
for (let i in arr) {
//此处的i是数组下标
console.log(arr4[i]);
}
for (let elem of arr) {
//此处的elem是数组元素
console.log(elem);
}
数组添加元素 push
给数组添加元素(尾插),使用push方法。
let arr4 = ['a', 'b', 'c'];
arr4.push('aaaaaaa');
for(let i = 0; i < arr4.length; i++) {
console.log(arr4[i]);
}
数组删除元素 splice
删除元素splice
这个方法相当于一个万能方法。可以用来插入,修改,删除。
splice(startindex, count, 变长参数)
startindex:从哪个下标开始进行操作。
count:操作元素数。
变长参数:将这里的内容替换到指定的范围内,可以有也可以没有。
如果没有变长参数,就相当于删除;
如果后面变长参数和前面指定的区间个数一样,就是修改/替换;
如果后面变长参数比前面的区间个数长,就是新增。
函数
开头有 function、函数名、形参列表,不用写返回值类型
//函数创建
function 函数名(形参列表){
函数体
return 返回值;
}
//函数调用
函数名(实参列表) //b
返回值 = 函数名(实参列表)
先定义后调用 或者 先调用后定义都可以
function hello() {
console.log('hello');
}
hello();
此处是不需要写类型的,啥类型都行,只要你传入的变量能够在函数内部正常工作即可
function add(x, y) {
return x + y;
}
如果实参个数少于形参个数,多出来的形参的值就是undefined。
function add(x, y) {
return x + y;
}
console.log(add('10')); //10undefined
如果实参个数更多,多出来的实参相当于没用上。
function add(x, y) {
return x + y;
}
console.log(add(10, 20, 30)); //30
当形参和实参个数不匹配,不会报错,只会尽可能的去执行。
如果实参个数更多,可以通过一个特殊的变量arguments,拿到所有的实参。
每个函数里面都会自动定义一个arguments变量,他是一个数组,包含了所有的实参。
function add() {
let result = 0;
for (let elem of arguments) {
result += elem;
}
return result;
}
console.log(add(10));
console.log(add(10,20));
console.log(add(10,20,30));
console.log(add(10,20,30,40));
函数表达式
let add = function() {
let result = 0;
for (let elem of arguments) {
result += elem;
}
return result;
}
先定义了一个没有名字的匿名函数,然后把匿名函数赋值给一个add变量。
add变量的类型,就叫做function类型。对于function类型的变量是可以直接调用的。
js中,可以像普通变量一样,把函数赋值给一个变量。
同时也可以把函数作为另一个函数的参数,或者把函数作为另一个函数的返回值。这一点 java中无法做到
这个特性称为函数在js中是一等公民
function one() {
console.log('one')
return two(); //单纯的函数调用
}
function two() {
return 100;
}
console.log(one());
返回one 100
function one() {
console.log('one')
return two; //把函数作为另一个函数的参数
}
function two() {
return 100;
}
let q = one();
q();
返回one
js中变量的作用域
当代码中访问某个变量的时候,要去哪里找这个变量
js会先找当前作用域,如果当前没有,就往上层作用域找。
一直往上直到全局作用域,如果还找不到,报undefined。
let num = 1;
function test1() {
let num = 2;
function test2() {
let num = 3;
console.log('test2:' + num);
}
test2();
console.log("test1:" + num);
}
test1();
console.log('global:' + num);
test2:3
test1:2
global:1
let num = 1;
function test1() {
// let num = 2;
function test2() {
// let num = 3;
console.log('test2:' + num);
}
test2();
console.log("test1:" + num);
}
test1();
console.log('global:' + num);
test2:1
test1:1
global:1
对象
js不是面向对象的编程语言,但是存在对象概念。js中关于对象的设定和Java差别很大。
js中没有封装、继承、多态,甚至没有类,JS中所有对象类型都是object。
js的对象有属性,也有方法。(方法本质上也是属性,因为函数在js中是一等公民)
let student = {
name: 'zhangsan',
age: 25,
height: 180,
run: function() {
console.log('hhhhh');
},
jump: function() {
console.log('qqqqq');
}
};
console.log(student.age);
console.log(student.name);
student.jump();
另一种创建方法。js中的对象里面有啥属性,方法,都不是提前约定好的,而是随时可以添加的。
let student = new Object();
student.name = "张三";
student.age = 25;
student.run = function() {
console.log('hhhhh');
}
web api
重点了解dom api:操作页面上的元素。把页面上的HTML元素和JS对象关联起来。
DOM:document object model (文档对象模型)
html的每个标签,都可以映射到js中的一个对应对象
- 标签上显示什么,都可以通过js对象感知到
- js对象修改对应属性,能够影响到标签的展示。
通过dom,就可以让js代码来操作页面元素。
常用的DOM API
querySelector
选中页面元素 querySelector(CSS选择器)
let elem1 = document.querySelector();
document是浏览器中的全局对象,任何一个页面都会有一个document对象,所有的dom api 都是通过document对象来展开的。
<div class="box">abc</div>
<div id="id">def</div>
<h3>
<span>
<input type="text">
</span>
</h3>
<script>
let elem1 = document.querySelector('.box');
console.log(elem1);
console.dir(elem1); //当作对象打印 打印元素全部属性
</script>
如果有多个.box
,默认选中的是第一个。
如果想全都选出来,使用 querySelectorAll
(返回数组)
事件
事件就是针对用户的操作进行的一些响应。
我们要能够和用户进行交互,就需要知道用户都干了些什么,用户做的一些动作,就会在浏览器中产生一些事件,代码需要针对这些事件做出反应。
事件(鼠标点击、双击、移动;键盘按下、调整浏览器窗口)
事件的三个要素:
- 事件源:那个元素产生的事件
- 事件类型:点击、双击、移动、键盘按下
- 事件处理程序:事件发生之后,要执行那个代码(要执行的代码都是提前设定好的)
在前端页面中,针对不同的事件,有不同的处理方式,都是在最开始设定好的(事件绑定)
最简单的方式:在元素中使用onXXX,绑定一个事件处理程序
<div class="box" onclick="alert('hello')">abc</div>
- 事件源:class=“box”
- 事件类型:onclick
- 事件处理程序:alert(‘hello’)
更推荐的写法:将控制事件语句单独写在script中
let div = document.querySelector('.box');
div.onclick = function() {
alert('hello');
}
获取 / 修改元素内容
先获取到该元素,使用innerHTML属性,就能够拿到元素里面的内容,修改该属性,就会影响到界面的显示。
每点击一次,.box div 中加一个a
let div = document.querySelector('.box');
div.onclick = function() {
console.log(div.innerHTML);
div.innerHTML += 'a';
}
chrome控制台默认会把相邻的相同的日志合并
获取 / 修改元素属性
html标签的属性,也会映射到JS对象中。
修改img中的src属性
<img src="11.png" alt="">
<script>
let img = document.querySelector('img');
img.onclick = function() {
console.log(img.src);
img.src = '22.png';
}
</script>
获取 / 修改表单元素属性
表单元素(input、textarea、select)有一些特别的属性,普通标签没有
<input type="text">
<button>点我一下</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function() {
console.log(input.value);
console.log(input.innerHTML); //不能写innerHTML
}
</script>
innerHTML得到的是标签的内容(开始标签和结束标签中间的部分),而input标签是单个标签,没有内容。
实现功能:给input里面放数字,每次点击按钮,让数字 +1 并显示
<input type="text">
<button>点我一下</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function() {
// console.log(input.value);
// console.log(input.innerHTML); //不能写innerHTML
let value = input.value;
value += 1;
input.value = value;
}
</script>
由于value属性是一个string类型,直接 +1 就变成字符串拼接了,因此需要把字符串转成整数类型。
加parseInt
转成int
<input type="text">
<button>点我一下</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function() {
// console.log(input.value);
// console.log(input.innerHTML); //不能写innerHTML
let value = parseInt(input.value);
value += 1;
input.value = value;
}
</script>
type
切换密码是否显示
<input type="text">
<button>隐藏密码</button>
<script>
let input = document.querySelector('input');
let button = document.querySelector('button');
button.onclick = function() {
if(input.type == 'text') {
input.type = 'password';
button.innerHTML = "显示密码";
} else {
input.type = 'text';
button.innerHTML = "隐藏密码~";
}
}
</script>
获取 / 修改样式属性
- 修改内联样式(修改style属性的值)
style里的属性名字都是和CSS中的一致。(将CSS的脊柱命名换成驼峰命名即可)
关于CSS的驼峰命名:
- CSS里面是不需要进行算术运算,不会被当做减号/负号
- CSS不区分大小写的.使用驼峰不合适 fontSize 和 fontsize 一样
<div style="font-size: 20px;">这是一个div,点击之后字体放大</div>
<script>
let div = document.querySelector('div');
div.onclick = function() {
//先获取当前字体大小
console.log(div.style.fontSize);
let fontSize = parseInt(div.style.fontSize);
fontSize += 10;
div.style.fontSize = fontSize + "px";
}
</script>
- 修改元素应用的CSS类名
应用:切换日夜间模式
<div id="one" class="light" style="font-size: 20px; height: 500px;">这是一个div,点击之后字体放大</div>
<style>
.light {
/* 日间模式 */
color: black;
background-color: #fff;
}
.dark{
/* 夜间模式 */
color: #fff;
background-color: #000;
}
</style>
<script>
let div = document.querySelector('#one');
div.onclick = function() {
// 点击div 切换到日间模式和夜间模式
if(div.className == 'dark') {
div.className = 'light';
} else {
div.className = 'dark';
}
}
</script>
上述操作都是针对当前页面上已有的元素进行操作的。
下面介绍关于新增和删除元素
新增元素 createElement
- 创建元素
- 把这个元素放到dom树
<div class="one">这是一个div</div>
<!-- 给 div 中放一个输入框 -->
<script>
let input = document.createElement('input');
input.value = "hello"; //输入框里默认显示hello这个内容
//把元素放到dom树上
let div = document.querySelector('.one');
div.appendChild(input); //把元素添加到子元素的末尾
</script>
往 ul
中添加了若干个 li
标签
<ul>
<li>l1</li>
<li>l2</li>
</ul>
<script>
let ul = document.querySelector('ul');
for(let n = 3; n < 10; n++) {
let li = document.createElement('li');
li.innerHTML = n + "" + n;
ul.appendChild(li);
}
</script>
appendChild
:把元素添加到子元素的末尾(尾插)
insertBefore
:把元素加到指定子元素的前面(中间位置插入)
删除元素 removeChild
parentElem.removeChild(childElem);
删除列表中的33元素
<ul>
<li>11</li>
<li>22</li>
</ul>
<script>
let ul = document.querySelector('ul');
for(let n = 3; n < 10; n++) {
let li = document.createElement('li');
li.innerHTML = n + "" + n;
ul.appendChild(li);
}
//删除33这个元素
let toDelete = document.querySelectorAll('li')[2];
ul.removeChild(toDelete);
</script>
猜数字
<div>请输入要猜的数字</div>
<input type="text">
<button>提交</button>
<!-- 使用这个 div 显示结果 -->
<div class="result"></div>
<script>
//1. 生成1-100的随机整数
let toGuess = parseInt(100 * Math.random() + 1);
console.log(toGuess);
//2.进行猜数字操作
let button = document.querySelector('button');
let input = document.querySelector('input');
let resultDiv = document.querySelector('.result'); //按照类名找到
button.onclick = function() {
//3. 取出输入框中的内容
if(input.value == "") {
//用户什么都没输入,直接返回
return;
}
let inputNum = parseInt(input.value);
//4.比较大小关系
if(inputNum < toGuess) {
//低了
resultDiv.innerHTML = "低了";
} else if(inputNum > toGuess) {
//高了
resultDiv.innerHTML = "高了";
} else{
//猜中了
resultDiv.innerHTML = "猜中了";
}
}
</script>