js基础
js引入方式
- 行内式:通过向 html 元素行内添加一些 js 代码,如给 div 绑定点击事件
<div onclick="alert('这是js代码')">这是一个div</div>
- 内嵌式:在 html 文档中写一个 script 标签,把我们的 js 写在 script 标签内
<script>
alert('这是内嵌式js代码')
</script>
- 外链式:在 html 文档中写一个 script 标签,并且设置 src 属性,src 的属性值引用一个 js 文件资源,而 js 代码写在 js 文件中
使用外链式引入 js 文件时,script 标签里面不能再写 js 代码了,即使写了也不会执行。
<script src="js/1.js"></script>
无论是内嵌式还是外链式,都建议把 script 标签写在 body 结束标签的前面。
一、 浅谈前端发展史
第一阶段:C/S (client server) -> B / S (browser server)网页制作
技术栈:PhotoShop、HTML、CSS
第二阶段:从静态到动态,从后端到前端 前端开发工程师
前后端分离:
后端:完成数据的分析和业务逻辑的编写(包含API接口编写)
前端:网页制作、JS交互效果、数据的交互和绑定
技术栈:JavaScript 、 Ajax(跨域技术)、jQuery ...
第三阶段:从前端到全端(从PC端到移动端)
技术栈:H5、CSS3、响应式布局开发,Zepto、Hybrid(混合app开发)微信小程序...
第四阶段:从全端到全栈
全栈开发:前后端都可以开发(严格意义讲,一种语言完成前段后开发)
技术栈:NODE(基于js编程语言开发服务器端程序)、Express/Koa...
二、关于浏览器的内核和引擎
Webkit(v8引擎):大部分浏览器
Gecko:火狐
Trident:IE
...
W3C:万维网联盟,制定编程语言的规范与标准
开发者按照规范编写代码,浏览器开发商也会开发一套按照规范把代码渲染成页面的东西(这个东西就是内核或者引擎)
浏览器内核的作用:按照一定的规范,把代码基于GPU(显卡)绘制出对应的图形和页面等;
为啥会出现浏览器兼容:
- 部分浏览器会提前开发一些更好的功能,后期这些功能会被收录到 W3C 规范中,但是在收录之前,会存在一定的兼容性
- 各个浏览器厂商,为了突出自己的独特性,用其他方法实现 W3C 规范中的功能
...
三、JavaScript
JS:轻量级的客户端脚本编程语言
- 编程语言
HTML + CSS 是标记语言
编程语言是具备一定逻辑的,拥有自己的编程思想(面向对象【oop】、面向过程编程)
- 面向对象
- C++
- JAVA
- PHP
- C#
- JS
- ...
- 面向过程:
- C
2.目前的 JS 已经不是客户端语言了,基于 NODE 可以做服务器端程序,所以 JS 是全栈编程语言
- 学习 JS,我们学习它的几部分组成
- ECMAScript(ES):js的核心语法
- DOM: Document Object Model文档对象模型,提供各种API(属性和方法)让 JS 可以获取或者操作页面中的HTML元素(DOM和元素)
- BOM:Browser Object Model 浏览器对象模型,提供各种 API 让 js 可以操作浏览器
四、ECMAScript
它是 JS 的语法规范,JS 中的变量、数据类型、语法规范、操作语句,设计模式等等都是 ES 规定的;
值得注意的是 js 的注释方式:注释是一项备注内容,给人看的,代码执行时会忽略注释内容。
- 单行注释: // 两个单斜线
- 多行注释:/多行注释内容写在两个星号之间__/
五、变量(variable)
它不是具体的值,只是一个用来存储具体值的容器或者代名词,因为它存储的值可以改变,所以称为变量。
基于 ES 语法规范,在 JS 中创建变量有以下方式:
- var(ES3)
- function (ES3)创建函数(函数名也是变量,只不过存储的值是函数类型而已)
- let (ES6)声明变量
- const (ES6)创建常量(常量就是恒定不变的值,如光速就是常量)
- import (ES6)基于ES6的模块到处规范导出需要的信息
- class (ES6) 基于ES6创建 类
/*
* 语法:
* var 变量名 = 值
* let 变量名 = 值
* const 变量名 = 值
* function 函数名 () {
* // 函数体
* }
*/
var n = 13;
n = 15;
alert(n + 10); // => 弹出来25 此时的 N 代表15
const m = 100;
m = 200; // Uncaught TypeError: Assignment to constant variable (常量存储的值不能被修改,能够被修改的就是变量了)
创建变量,命名的时候要遵循一些规范
- 严格区分大小写
- 遵循驼峰命名法:按照数字、字母、下划线或者$来命名(数字不能作为开头),命名的时候基于英文单词拼接成一个名字(第一个单词字母小写,其余每一个有意义单词的首字母都大写)
- 不能使用关键字和保留字:在 js 中有特殊含义的叫做关键字,未来都可能成为关键字的叫做保留字
var n = 12;
var N = 12; // 变量 n 和变量 N 不是同一个变量
var studentInfo = 'xyz'; // 驼峰命名法
// 变量要具有语义化
add / create / insert
del (delete) / update / remove(rm)
info / detail
log
六、数据类型
数据类型是一门语言进行生产的材料,JS 中包含的值有以下这些类型:
- 基本类型:
- 数字 number
- 字符串 string
- 布尔 boolean
- null
- undefined
- Symbol 表示一个唯一值(ES6新增)
- 引用数据类型:
- 对象object
- 普通对象
- 数组对象
- 正则对象
- 日期对象
- ...
- 函数function
- 对象object
// [基本数据类型]
var n = 13; // => 0 1 -13 13.2都是数字, 此时变量 n 存储的就是一个数字;数字中有一个特殊的值:NaN(not a number),表示不是一个有效的数字,但是仍然是一个数字类型
var s = ''; // =>如 '' '13' "13" "name" "age" JS 中所有用单引号或者双引号包裹起来的都是字符串,字符串表示的值是当前引号中包裹的值(一个字符串由零到多个字符串组成)
var b = true; // => 布尔类型只有两个值 true 真 false 表示假
var empty = null; // => 变量 empty 表示 null 空
var notDefined = undefined; // 变量 notDefined 表示 undefined(undefined 这个单词的意思就是未定义);
// Symbol: 用来创建一个唯一值,和谁都不会重复。下面等号右侧虽然长的一样,但是 s1 和 s2 变量代表两个不同的值。
var s1 = Symbol('珠峰');
var s2 = Symbol('珠峰');
// [引用数据类型]
// => 对象
var obj = {name: '珠峰培训', age: 9}; // => 普通对象:由大括号包裹起来,里面包含多组属性名和属性值(name 和 age 叫做属性名(又称键,英文名 key),而 '珠峰培训'/9叫做属性值(又称值,英文名 value),所以对象又叫做键值对集合或者key/value集合)
var obj2 = {}; // => 变量 obj2 表示空对象;
// => 数组
var ary = [1, 2, 3, 4, 5]; // => 数组对象:用中括号包裹起来,包含0到多项内容,每一项之间用逗号(英文逗号)分隔。
var ary2 = []; // => 变量 ary2 表示一个空数组
// => 正则:用来匹配字符串的规则
var reg = /^abc$/; // => 两个斜线中间的叫做元字符
// => 函数:需要多次重复使用的代码或者有特定功能的代码可以封装成一个函数;
function fn () {// => 函数体}
// function 叫做关键字,用于声明函数变量
// fn 叫做函数名,函数名也需要满足变量声明的条件(本质上函数名也是变量名,只不过这个变量名代表的是一个函数数据类型的值)
// () 【声明函数时】fn后面的这个小括号表示的是形参入口
// {} 写在函数中的 {} 表示函数体,这里面写需要执行的代码
// ....
七、JS代码运行及常用输出方式
- alert方法(函数): 在浏览器中通过弹窗的方式输出(浏览器提示框)
var num = 12;
alert(num); // alert() 读作:alert方法执行【写在方法名后面的“()”读作 “执行” ,就是把alert函数里面的代码执行一遍】。把想输出的东西放在小括号里;
var course = '珠峰培训js基础课程';
alert(course);
- console.log方法:在浏览器控制台输出日志。console是浏览器的开发者工具的一个页卡(在浏览器中按下F12按键【部分电脑需要按下Fn和F12】)
// console.log() 读作 console.log 方法执行,把想要输出的变量或者内容放在小括号里。
var name = '珠峰培训-马宾';
console.log(name);
- innerHTML/innerText属性; 修改元素中的 HTML 或者文本;
var box = document.getElementById('box'); // => 在document(整个HTML文档中)下面查找 id 为 box 的元素。
// 语法:元素对象.innerHTML/innerText = '想要显示的内容'; 【想要显示的内容必须是一个字符串类型的值】
box.innerHTML = '<h1>珠峰培训js基础课程第一周</h1>';
box.innerText = '<h1>珠峰培训js基础课程第一周</h1>';
// box.innerHTML/box.innerText = '字符串' 读作:将 box 的 innerHTML 或 innerText 修改为 '字符串'
// => 我们发现同样是包在字符串里面的内容,通过 innerHTML 的方式浏览器会将<h1>识别成 HTML 内容;但是 innerText 不能识别,而是你字符串里面写什么,页面就输出什么;
八、有效数字检测、数据类型转换、数据类型检测
有效数字检测
- 有效数字检测 isNaN() 方法;非有效数字:NaN(not a number)
isNaN(需要检测的值):检测当前是否是一个有效数字,如果是一个有效数字,isNaN执行后就会得到一个 false,否则 isNaN 执行后得到一个 true;(我们得到的这个 false 或者 true 称为 isNaN 函数的返回值【就“结果”的意思】)
语法:isNaN(需要检测的值)
var num = 12;
var result1 = isNaN(12); // -> 检测 num 变量存储的值是否为非有效数字,12是数字,所以 isNaN 执行后得到一个 false;
var result2 = isNaN('13'); // -> false
var result3 = isNaN('珠峰'); // -> true 因为汉字不是数字
var result4 = isNaN(false); // -> false
var result5 = isNaN(null); // -> false;
var result6 = isNaN(undefined); // -> true
var result7 = isNaN({name: '珠峰培训'}); // -> true
var result8 = isNaN([12, 23]); // -> true
var result9 = isNaN([12]); // -> false
var result10 = isNaN(/^$/); // -> true
var result11 = isNaN(function () {}); // -> true
思考:为啥小括号里的不是数字也能得到结果?这是isNaN的检测机制:
1、首先验证当前要检测的值是否为数字类型的,如果不是,浏览器会默认的把值转换为数字类型
把非数字类型的值转换为数字:
- 其他基本类型转换为数字:内部隐式调用Number方法
Number(需要转换的值); 是强制转换
[字符串转数字]:如果字符串里面都是数字,那么返回这个数字,如果有非数字的因素会返回NaN.
Number('13') // -> 13
Number('13px') // NaN 字符串中 px 不是数字
Number('13.5') // 13.5 可以识别小数点
[布尔值转数字]
Number(true); // -> 1
Number(false); // -> 0
[null、undefined转数字]
Number(null); // 0
Number(undefined); // NaN
- 引用数据类型转数字:先调用引用数据类型值的 toString 方法将引用数据类型转化为字符串,然后再将字符串转换为数字。
[对象转数字]
Number({}) // NaN; 其内部机制:({}).toString() -> '[object Object]' -> Number('[object Object]') -> NaN
[数组转数字]
Number([12, 23]) // NaN; 内部机制:[12, 23].toString() -> '12, 23' -> Number('12, 23') -> NaN
[正则]
Number(/^\d$/) // NaN; 内部机制:/^\d$/.toString() -> '/^\d$/' -> Number('/^\d$/') -> NaN
2、当前检测的值已经是数字类型,是有效数字就得到一个 false,不是就会得到一个 true;(在数字类型中只有 NaN 不是有效数字,其余的都是有效数字)
Number(1); // false
Number(NaN); // true
3、NaN 的比较
NaN == NaN // 返回 false;( == 是比较运算符,一个等号是赋值)
这是因为什么呢?因为 NaN 只是表示非数字,字符串 'a' 是非数字,'张三'也是非数字。但是 a 和 张三不相等。
if (Number(num) == NaN) {
// if 是 js 中用来做判断的语言结构,小括号里表示条件,如果条件成立就执行花括号里面的代码
alert('珠峰10年,专注前端');
}
// 上面花括号里面的代码永远不会执行,因为 Number 方法得到的结果只有两种情况,要么是数字,要么是 NaN。如果得到一个数字,数字和 NaN 不相等,如果是 NaN,NaN 和 NaN 也不相等。
数据类型转换(parseInt、parseFloat方法)
作用和 Number 方法相似,都是把非数字类型值转换为数字,区别在于 Number 方法是强制转换,即要求被转字符串中必须都是数字,如果不满足这一条件直接得到 NaN,而 parseInt 和 parseFloat 则是非强制转换。
parseInt:把一个字符串中的整数解析出来
parseFloat:把一个字符串中整数和小数包含小数点都解析出来
parseInt('13.5') // 13
parseFloat('13.5') // 13.5
parseInt('width: 13.5px'); // NaN
parseFloat('width: 13.5px'); // NaN
注意:无论是 parseInt 还是 parseFloat 都是从字符串的最左边开始查找有效数字,直到遇到第一个非有效数字字符就停止查找,如果第一个就不是有效数字,那么直接回返回 NaN,并且停止查找。
数据类型检测:
检测数据类型一共有四种方式:
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
我们这里先讲 typeof 运算符
语法:typeof 被检测的值返回被检测值的数据类型;
console.log(typeof 1); // number
console.log(typeof 'zhufengpeixun'); // string
console.log(typeof true); // boolean
console.log(typeof null); // object
console.log(typeof undefined); // undefined
console.log(typeof {}); // object
console.log(typeof []); // object
console.log(typeof /^/); // object
// 思考?typeof 运算符的返回值是个什么数据类型?
var result = typeof 1;
console.log(typeof result); // string
// 面试题
console.log(typeof typeof 1); // string
typeof 是有局限性的,检测基本数据类型时,typeof 检测 null 会返回 object,因为 null 是空对象指针。同时,typeof 检测引用数据类型时,不能具体区分是哪一种对象数据类型(对象、数组、正则等)只会统一返回object。
2-js基础教程
一、普通对象
js中的普通对象:无序的键值对集合。
- 由大括号包裹起来的{key: value}
- 由零到多组属性名和属性值(键值对)组成。属性名可以是数字、字母、或者下划线等,并且属性名都是字符串类型的。
属性是用来描述当前对象特征的,属性名是当前对象具备的特征,属性值是这个特征的描述,一组属性名和属性值成为一组键值对
声明对象
var feTraining = {
name: '珠峰培训',
age: 9,
characters: '专注前端10年',
9: 'age'
}
对象的操作:键值对的增删改查
- 获取对象的某个属性的值
- 对象.属性名
- 对象['属性名']
console.log(feTraining.name);
console.log(feTraining['name']);
var str = 'age';
console.log(feTraining[str]); // 9
如果用. 后面的属性名不用写引号,如果使用[],属性名需要用字符串包裹
如果属性名是数字,只能使用 []
方括号里面还可以写变量或者表达式
如果获取一个对象不存在的属性,会得到一个 undefined
- 增加/修改
js 对象中的属性名是不允许重复的,是唯一的
如给一个对象的属性赋值,有两种情况:- 如果对象之前不存在这个属性,那么就是给这个对象增加一个属性,值是等号右侧的值
- 如果对象之前已经存在这个属性了,再赋值就是修改对象中的这个属性的值
feTraining.courses = 'JS高级+vue+react+node'; // feTraining 之前不存在 courses 这个属性,所以是增加;
console.log(feTraining);
feTraining.name = 'Everest Training'; // feTraining 之前就存在 name 属性,所以是修改
console.log(feTraining);
-
删除
-
彻底删除:把对象的属性名和属性值都删除。 delete obj['name']
-
软删除:将对象的某个属性的值赋值为null。 obj.name = null
delete feTraining.age;
console.log(feTraining);
feTraining.courses = null;
console.log(feTraining); // course 属性名还在,只是值为 null 了
思考?
var obj = {
name: '珠峰培训',
age: 10
};
obj.name // '珠峰培训'
obj['name'] // '珠峰培训'
obj[name] ?? => name 和 'name'有什么区别?'name' 表示的是一个字符串,而 name 表示一个变量名
对象中的属性名都是字符串类型的
二、数组对象
数组是【有序】的键值对集合;但是数组的键是浏览器设置的,不需要我们手动设置,并且键都是从0开始的数字,我们称数字属性名为【索引】。数组的第一项的对应的索引是0,第二项对应的索引是1,以此类推,第n项对应的索引是 n - 1。
var ary = [12, 23]; // ? 12和23是都是属性值,属性名呢?
console.log(ary); // 从控制台可以发现是有键的,并且键都是数字
数组的操作
数组的键是数字,所以只能用方括号的方式获取、修改,而且写在方括号里面的属性名不需要用引号包裹;
var ary = [12, 23];
console.log(ary[0]);
console.log(ary.0); // 报错
console.log(ary[1]);
console.log(ary[2]); // 访问一个数组不存在的索引,会得到一个 undefined
三、基本数据类型和引用数据类型的区别
var a = 12;
var b = a;
b = 13;
console.log(a); // 12
console.log(b); // 13
var obj1 = {
name: '珠峰',
age: 10
};
var obj2 = obj1;
obj2.age = 100;
console.log(obj1.age); // 100
console.log(obj2.age); // 100
为什么会有这种情况?
基本数据类型(也叫做值类型)的操作,直接操作就是这个值,意思就是说变量本身就代表这个值。所以: var b = a; a存储12这个值,然后声明一个变量 b,然后让b = a,就是让b = 12。这样和 var b = 12本质上没有任何区别;
引用数据类型都是存放在堆内存空间中的,同时这个堆内存空间有一个十六进制的内存地址(例如aaafff000)。我们在声明一个变量存储引用数据类型时,不是直接把对象赋值给变量,而是把对象的堆内存地址赋值给变量。所以 obj1 拿到的知识这个堆内存地址 aaafff000;
所以引用数据类型的操作不是直接操作的值,而是操作它的引用数据类型的堆内存地址。所以var obj2 = obj1; 只是把 obj1 代表的堆内存地址赋值给了变量 obj2。
所以 obj2.age = 100;是通过 obj2 的堆内存地址找到堆内存地址中的存储的 age 的值,把它修改成100。同时,我们访问 obj1.age 时也是先通过 obj1 存储的堆内存地址找到内存空间,然后从里面把属性age的值取到,此时这个内存空间中的值已经修改成100了。所以obj.age 也是100
四、布尔类型、布尔运算
布尔类型值只有两个值,true 和 false;布尔运算用来测试真假值,即运算结果是真的还是假的,通常结合 js 的判断语句(if/switch-case/三元表达式)使用。
其他数据类型和布尔值进行转换
- Boolean方法
语法:Boolean(需要转换的值) ;得到转换后的规则
var boo = Boolean(1);
var boo2 = Boolean(0);
console.log(boo, boo2); // true false
- !运算符(取反运算符)true 取反就是 false,而 false 取反就是 true
运算符是有固定功能的关键字或者符号。它通过操作值也可以得到返回结果,与方法不同的是运算符不需要小括号。
语法:!需要取反的值 ;得到取反后的布尔值。其内部机制是先把其他数据类型转换成布尔值,然后再取反。
转换规律:在 js 中只有 0/NaN/空字符串''/null/undefined 这5个值转换成布尔值是 false,其余的都是 true。
var str = '珠峰培训,10年专注前端';
var result = !str;
// 内部运作机制:
// 第一步先将str转换成布尔值,str不属于那5个值,所以 Boolean(str) => true
// 然后再取反,true 取反 => false
console.log(result); // false
- !! 运算符 等效于 Boolean 方法
语法:!!需要转换的值;
var num1 = !!1;
var num2 = !!0;
console.log(num1, num2); // true false
console.log(!!{}); // true
console.log(!![]); // true
console.log(!!{name: 'zhufeng'}); // true
五、null 和 undefined
null 空对象指针;不占内存,通俗理解就是人为的手动先赋值为 null,后面程序中我们会再给它赋值为其他值;
undefined 未定义。多数情况是某些浏览器内置机制设置的默认值,声明一个变量不赋值,这个变量的默认值就是undefined
六、js中的判断语句
判断语句是流程控制的重要语句,其作用是当满足某些条件时才能执行某些代码
1、if/else if/else
// 单独使用if
if (条件) {
// 浏览器会对条件进行布尔运算,即求出条件时 true 还是 false。条件为 true 时,即条件成立的时候才会执行这个花括号里面的代码
}
// 两种情况,结合 else
if (条件) {
// 条件为 true 时
} else {
// 不满足条件的时候要执行的代码
}
// 多种情况,结合 else if
if (条件1) {
// 条件1为 true 时
} else if (条件2) {
// 条件2为 true 的时候要执行的代码
} else {
// 上面条件都不满足条件的时候要执行的代码
}
示例:
var num = 6;
if (num > 6) {
num++; // => num = num + 1; 在自身上累加一个
} else if (num >= 10) {
num--;
} else {
num+=2
}
console.log(num);
只要有一个条件成立,后面不管是否还有成立的条件,都不会在执行了
var num = 10;
if (num > 5) {
num += 2;
} else if (num > 8) {
// 虽然 num 满足大于8,但是再上面已经执行过num>5的代码,所以这里不会执行
num += 3;
} else {
num += 4;
}
console.log(num); // 12
2、条件怎么写?
if (条件) 条件最终需要的是一个布尔值,然后根据是 true 还是 false 来判断条件是否成立。如果条件里面写的是可以返回布尔值的表达式,那么就利用这个表达式的返回结果;如果不是返回布尔值,那么浏览器会自动把它转换成布尔值,然后用转换出来的结果判断条件是否成成立
常见比较运算符:比较运算符都会返回布尔值
- 大于(>), a > b, 当 a 大于 b 时返回 true,否则返回 false
- 大于等于(>=), a >= b ,当 a 大于等于 b 时返回 true,否则返回 false
- 小于(<),a < b
- 小于等于(<=)
- 不等于(!=)、
- 等于(相对比较== 或者 绝对比较===)
- == 是相对比较,只要两边的值相同就行,不比较类型,如 1 == '1' 返回 true
- === 是绝对比较,两边值相同还不够,还要比较类型。1 === '1' 返回 false,因为1是 number,而'1'是 string,类型不同
console.log(1 > 0); // true
console.log(1 < 0); // false
console.log(1 == '1'); // true
console.log(1 === '1'); // false
条件常见形式:
- 使用比较运算符,直接返回布尔值
- 如果是数学表达式,那么会先运算求值,然后再把运算出来的结果转换成布尔值。
在js中,+ - * / % 都是数学运算,除 + 以外,其余的运算符在运算时,如果遇到非数字类型的值,首先会转成数字类型(Number),然后再进行运算
if ('3px' + 3) {
// + 操作符在两边都是数字时才是加法运算符,如果有一个不是数字,那么加好就是字符串拼接。
// 所以 '3px' + 3的结果是字符串'3px3',而字符串 '3px3'转换成布尔值以后是true,所以条件成立
}
if ('3px' - 3) {
// - 会调用Number()方法把'3px'转成数字,Number('3px') -> NaN,而NaN - 3 -> NaN,而NaN转成布尔值是false,所以条件不成立
}
- 其他情况,均会把条件转成布尔值。
练习
var num = parseInt('width: 35.5px');
if (num == 35.5) {
alert(0);
} else if (num == 35) {
alert(1);
} else if (num == NaN) {
alert(2);
} else if (typeof num == 'number') {
alert(3);
} else {
alert(4);
}
2、三元运算符
语法: 条件 ? 成立要做的事情 : 不成立要做的事情
相当于简单的 if else判断
并且三元运算符是有返回值的,当条件成立时三元运算符返回条件成立时的值,不成立时返回不成立的值。
- 一般情况
var num = 12;
if (num < 10) {
num++;
} else {
num--;
}
// 改写成三元运算符
num > 10 ? num++ : num--;
- 特殊情况:
- 如果三元运算符中条件成立或者不成立时不需要任何操作,我们用null/undefined/ void 0占位
// num > 10就++,否则啥也不做
num > 10 ? num++ : null;
num > 10 ? num++ : undefined;
num > 10 ? num++ : void 0;
- 如果在条件成立(或不成立)时有多条语句,需要用小括号括起来,每条语句;
var num = 10;
num >= 10 ? (num++, num*=2) : null;
3、switch case
语法:
switch (变量或者表达式) {
case 值1:
变量或者表达式的值是值1的时候执行的代码;
break;
case 值2:
变量或者表达式的值是值2的时候执行的代码;
break;
...
case 值n:
变量或者表达式的值是值1的时候执行的代码;
break;
default:
以上情况都不满足时,相当于else
}
switch case应用于变量(表达式)在不同值的情况下的不同操作,每一种 case 结束后都需要加break(break是结束整个判断);
var num = 12;
if (num == 10) {
num++;
} else if (num == 5) {
num--;
} else {
num = 0;
}
// 改写成 switch case
switch (num) {
case 10:
num++;
break;
case 5:
num--;
break;
default:
num = 0;
}
注意:switch case 中每一个 case 的比较都是基于 === 绝对相等来完成判断的。即 10 === '10' 是 false。真实项目中常用绝对比较。
3-js基础教程
一、逻辑运算符 || 和 &&
1、 || 表示或者,两者中有一个为 true,就返回 true
if (0 || 1) {
console.log('true')
}
if (0 || false) {
console.log('false')
}
if (true || 0) {
console.log(true);
}
2 && 是并且,两个值中必须两个都是 true,才返回 true
if (0 && 1) {
console.log(1, '0 && 1')
}
if (0 && false) {
console.log(2, '0 && false')
}
if (true && 0) {
console.log(3, 'true && 0');
}
3. || 和 && 也是有返回值的,
- || 如果第一个为 true 就返回第一个,如果第一个不为 true 就返回第二个
var r1 = 1 || 0;
console.log(r1);
var r2 = 0 || false;
- && 如果第一个为 true 返回第二个,如果第一个为 false 返回第一个
var r3 = 1 && 0;
var r4 = false && 0;
console.log(r3);
console.log(r4);
二、==和===的区别
== 在比较时等号左右两侧数据类型不同时会先转成相同数据类型,再比较
- == 是相对比较; === 是绝对比较
- 1.1 字符串 == 数字 ;字符串转换成数字
console.log(1 == '1'); // true
- 1.2 布尔值 == 数字; 布尔值转成数字
console.log(1 == true); // true;
- 1.3 布尔值 == 字符串; 布尔值转数字,字符串也转成数字,然后进行比较;
console.log(false == '0'); // true
- 1.4 null == undefined // true, null 和 undefined 和其他数据类型比较都是false
- 1.5 对象 == 对象; 比较的是空间地址,地址相同返回true
console.log({} == {}); // false
- 1.6 对象 == 字符串; 对象转成字符串,然后和字符串比较
console.log({} == '[object Object]'); // true
- 1.7 对象 == 布尔值;对象先转成字符串,再转数字,布尔值也转成数字,在比较这两个数字
console.log({} == true); // false
console.log([] == false); // true
- 1.8 对象 == 数字;对象先转成字符串,然后再转成数字
console.log({} == 1); // false
console.log([] == 0); // true
- 特殊:NaN 和 NaN 永远不相等
console.log(NaN == NaN); // NaN 和 NaN 永远不相等
三、for循环
for 循环 (for loop) 语句:按照一定的规律,重复去做某一件事情,此时就需要使用循环语句.
var ary = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
/* [
0: 1,
1: 2,
2: 3,
...
11: 12
length: 12 // length属性的值表示数组有多少项
]
*/
// 把数组里面的每一项都输出出来:
console.log(ary[0]);
console.log(ary[1]);
console.log(ary[2]);
console.log(ary[3]);
console.log(ary[4]);
console.log(ary[5]);
console.log(ary[6]);
console.log(ary[7]);
console.log(ary[8]);
console.log(ary[9]);
console.log(ary[10]);
console.log(ary[11]);
? 思考:我们发现上面的代码中除了方括号中索引不同,其他的代码都是相同的。
这个时候要是有一个变量i,然后让:
第一次时i=0,
第二次i=1,
第三次i=2,
...
依次类推,每一次帮我们给i加上1,那么到什么就不加了呢,因为i的最大索引是length-1,所以当i大于length-1之后就不再加了。
然后我们把代码中的索引换成i就可以了 console.log(ary[i]);
for (var i = 0; i < ary.length; i++) {
// 第一次循环: i = 0 i < 12 所以 ary[i] 是 ary[0]
// 第二次循环: i = 1 i < 12 所以 ary[i] 是 ary[1]
// ...
// i = 12 i < 12 => false 不再执行循环体,循环结束,
console.log(ary[i]);
}
console.log(i); // 在for的小括号里声明的变量可以在外面使用
for 循环语法
- 定义初始值 var i = 0
- 设定循环成立的条件 i < ary.length(如果条件成立执行循环,不成立则结束循环)
- 条件成立会执行循环体中的内容(循环体就是花括号中的代码)
- 执行累加 i++
var i = 0; 和i++ 可以不放到括号里,但是你写在括号里的这个变量和写在外面是一样的,在循环里i++更改的就是外面声明的这个i;
var k = 0;
for (;k < 5;) {
console.log(k);
k++;
}
console.log(k); // 在外面的k也被更改了,已经变成了5
倒着输出一个数组
- 把i的初始值设置为ary.length - 1,然后条件是 i >=0 ; i--;
var ary = [12, 23, 34];
for (var i = ary.length - 1; i >= 0; i--) {
console.log(ary[i]);
}
输入数组中的奇偶项
// 输出数组中的奇数项
// 偶数:能够被2整除的数字叫做偶数(整除:被除数除以余数商是整数且余数为0)
// 奇数:不能被2整除的数字
for (var j = 0; j < ary.length; j++) {
if (j % 2 === 0) {
// % 是取模运算符 ,就是取余数
// 0 % 2 余数是0
// 1 % 2 余数是1
// 3 % 2 余数是1
// 4 % 2 余数是0
console.log(ary[j]);
}
}
理解 break和 continue
- continue 跳出某一轮的循环,继续后面的循环
for (var i = 0; i < 10; i++) {
if (i === 5) {
continue; // 跳出i=5的那一次循环。结束本轮循环(循环体中的continue后面的代码将不再执行,继续执行下一轮循环)
}
console.log(i)
}
- break 结束整个循环
for (var i = 0; i < 10; i++) {
if (i === 5) {
break; // 结束i=5及以后所有的循环。break是强制结束整个循环,不做任何处理,同时循环体中的break后面的代码也不会执行了
}
console.log(i)
}
四、for in 循环
for in循环
for in 循环是专门用来遍历对象的,可以把对象里面的属性一个一个的遍历出来。
注意:for in只能遍历对象的可枚举属性。一般浏览器默认添加的都是不可枚举的属性。例如__proto**__**
var obj = {
name: '珠峰',
age: 10
};
for (var k in obj) {
// k 代表每次遍历时的属性名
console.log('k ', k);
console.log('obj[k]', obj[k]);
}
五、获取DOM对象
DOM对象:我们通过 js 的相关和 html 方法获取到的 html 文档中的元素
- document.getElementById()
通过 ID 获取页面中的元素对象 getElementById()方法
语法:document.getElementById('idbox');
参数:元素id, 'box'就是参数
返回值(函数执行过后的结果):如果获取到,就是获取到的 DOM 元素对象,如果获取不到就是 null;
- 解析:
- document 是根据 ID 查找的上下文,document 代表的是整个 HTML 文档(就是 html 标签自身及包裹的所有内容),getElementById 的上下文只能是 document
- 通过getElementById获取的元素是一个对象数据类型的值(里面包含了很多的内置属性,这些属性都是描述这个对象的)
- DOM对象的属性: 3. className: 存储的是字符串类型(string),代表的是当前元素的样式类名 4. id: 存储的是一个字符串类型(string),当前元素的ID名 5. innerHTML:字符串 存储的当前元素中所有的内容(包含标签,并且标签以字符串形式存在) 6. innerText: 存储当前元素中所有的文本内容(没有元素标签) 7. onclick: 鼠标点击事件 元素的点击事件属性,基于这个属性,我们可以给元素绑定点击事件 8. onmouseover: 鼠标划过事件 9. onmouseout: 鼠标划出事件 10. style 存储当前元素的所有的【行内样式】值(获取和操作的都只能是写在标签上的行内样式,写在样式表中的样式,无法通过这个属性获取到);
var box = document.getElementById('box');
console.log(box);
- getElementsByTagName()
通过标签名获取【元素对象集合】
- 解析:
- 语法:context.getElementsByTagName('标签名')
- 参数:标签名字符串
- 返回值:从 context 下面查到的指定标签名 DOM 元素对象组成的集合;这个集合中的每一项都是 DOM 元素对象;
- context 不是写死的,是我们指定的上下文。你想获取那个元素下面的指定标签元素集合,哪个元素就是上下文
var listContainer = document.getElementById('container');
var liList = listContainer.getElementsByTagName('li'); // 此时 listContainer 就是上下文
console.log(liList);
console.log(liList[0]);
console.log(liList[1]);
console.log(liList[2]);
liList[0].style.backgroundColor = 'red';
- 解析:
- 获取的是一个元素结合(HTMLCollection),元素集合也是一个对象数据类型的,结合和数组非常类似(数字作为索引,length代表长度),但它不是数组,而是叫做类数组。
- 和数组操作一样,通过[索引]的方式可以取出类数组的每一项。liList[0]获取的是第一项。
- liList.length 表示集合中li的数量
- 集合中的每一项都是元素对象,我们可以获取或者修改它的元素属性,如style、innerHTML、innerText
- 结合索引、length可以通过for循环把集合中的每一项获取出来。
? 思考 ? DOM对象也是对象,那么我们可以向操作普通对象那样操作它吗?比如说添加一个属性,或者修改某个属性?
DOM对象也是对象,我们也可以向操作对象的方式一样操作DOM对象
for (var i = 0; i < liList.length; i++) {
var cur = liList[i];
cur.myIndex = i; // 通过自定义属性存储这个元素在元素集合中的索引
console.log(cur);
}
六、隔行变色
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>珠峰-隔行变色</title>
<style>
* {
margin: 0;
padding: 0;
}
ul, li {
list-style: none;
}
.li-wrapper {
margin: 30px auto;
border: 1px solid #00b38a;
width: 500px;
}
.li-wrapper li {
height: 50px;
line-height: 50px;
text-align: center;
border-bottom: 1px darkblue dashed;
}
</style>
</head>
<body>
<ul id="liWrapper" class="li-wrapper">
<li>1item1</li>
<li>2item2</li>
<li>3item3</li>
<li>4item4</li>
<li>5item5</li>
<li>6item6</li>
<li>7item7</li>
<li>8item8</li>
<li>9item9</li>
<li>10item10</li>
</ul>
<script src="js/6-changeColor.js"></script>
</body>
</html>
// 1. => 获取元素 liWrapper 下的 li
var liWrapper = document.getElementById('liWrapper');
var liList = liWrapper.getElementsByTagName('li');
for (let i = 0; i < liList.length; i++) {
// 循环遍历元素对象,然后取出每一项
if (i % 2 === 0) {
// 如果是 i 是偶数
liList[i].style.backgroundColor = 'pink';
} else {
// 否则 i 是奇数
liList[i].style.backgroundColor = 'yellow';
}
}