第一章
前端三大语言:HTML(专门编写网页内容)、CSS(编写网页样式)、JS(专门编写网页交互行为)
能简写尽量简写
交互(IPO): ①用户输入;②执行: 程序接受、处理、响应数据;③输出处理结果
原生JS:不需要下载任何第三方文件,仅依靠浏览器就可直接执行的js代码
学习版本:ES6(2015)
现版本:ES7
中文乱码问题:引入的 .js 文件要与HTML文件一样是UTF-8模式,否则要在script中加 charset="gbk",但两个不能同时使用
API(Application Programming Interface,应用程序编程接口)是一套用来控制Windows的各个部件的外观和行为的一套预先定义的Windows函数
如果回调函数无法取名,可以在回调函数中调用定义的另一个有名的函数,以此来达到目的
判断数据是否为null、0、""、NaN、null、undefined一律可以省略等号后的值,只判断是否为false
js的事件监听跟css不一样,css只要设定好了样式,不论是原来就有的还是新添加的,都有一样的表现,而事件监听不同,只能给已经加载好的元素绑定事件
_______________________________________________________________________________________________
typeof null返回object
最初,JavaScript使用标记位来区分对象类型和原始类型:对象值使用0来标识,原始值使用1,因此,导致全为0的null被识别为object
JavaScript可以通过typeof ...来判断原始数据类型,但不能够准确判断引用类型,但可以用Object的toString方法来判断: console.log(Object.prototype.toString.call(要判断的数据))
一元运算符: 有些运算符两边有2个操作数,比如2+3、6%5等,这些叫做二元运算符
只有一个操作数的叫做一元运算符,它们的优先级高于二元运算符
一元运算符包括: ++(自加)、--(自减)、!(逻辑非)
JS的运算规则: 优先级相同的运算符从左向右计算(赋值运算符相反)
var a=1;b=++a+a++; 表示 b=2+2;
var a={n:1};
var b=a;
a.x=a={n:2}; //从左往右读(取出来),从右往左执行
//先执行a.x={n:2},再执行a={n:2}
console.log(a.x); //undefined
console.log(b.x); //{n:2}
console.log(a); //{n:2}
console.log(b); //{n:1, x:{n:2}}
_______________________________________________________________________________________________
1、Javascript概述
Javascript运行于Javascript 【解释器/引擎】中的解释性脚本语言
Javascript运行环境:1、Javascript解释器 :NodeJS
2、嵌入在浏览器中的内核(引擎)
解释型:无需编译,直接运行,出错就停止
脚本语言:纯文本语言
JS解释器和JS引擎:1、独立安装的JS解释器:NodeJS
2、嵌入在浏览器内核中的JS解释器:只要有浏览器,就能运行JS
2、Javascript 发展
①1992年 Nombas公司开发了一款脚本语言 ScriptEase ,可以嵌入在网页中
②1995年 Netscape(网景)公司为Navigator2.0浏览器开发了一款脚本语言 LiveScript,为了蹭热点将其命名为 Javascript,其实Javascript与Java没有一点关系
③1996年,Microsoft ,为了IE3.0,发布了一个Javascript克隆版本 JScript
④1997年 Javascript1.1 作为草案提交给了ECMA(欧洲计算机制造商协会)→ECMA-262标准→ECMAScript(ECMA制定的JavaScript语言国际标准,规定了JS语言的核心语法)
3、Javascript (原生JS)的组成
① 核心(ECMAScript,简称ES,ECMA制定的JavaScript语言国际标准,规定JS语言的核心语法)
② 文档对象模型(DOM---Document Object Model)允许让JS和HTML元素进行对话
专门操作网页内容的API
③ 浏览器对象模型(BOM—Browser Object Model)允许让JS和浏览器进行对话和操作
专门操作浏览器窗口的API
4、Javascript特点:
①任何编辑工具(例如:记事本)都可以编写Javascript,语法类似于Java,C,...
②无需编译,由JS解释器运行(自上向下边读边解释边执行,后解释的相同内容会覆盖先解释的)
赋值: 从左往右读(取出来待执行),从右往左执行(赋值)
运算:从左往右计算
③弱类型语言:声明变量时,不必提前规定变量的数据类型,先后可保存不同类型的数据,由值来自动隐式转换数据类型
④基于对象的编程语言———万物皆对象
5、 Javascript的用途
①客户端Javascript:浏览器中运行
1、客户端数据计算
2、客户端表单输入验证
3、浏览器事件的触发和处理
4、客户端动画效果特效制作
5、服务器的异步数据提交(ajax)
②服务器端Javascript:1、分布式运算 2、实时服务器 3、窗口应用 4、网络应用
_______________________________________________________________________________________________
Javascript基础语法
1、JS运行在脚本解释引擎:专门解析JS语言,并执行js程序的小软件
浏览器内核:负责页面内容的渲染,由两部分组成:
①内容排版引擎:解析 HTML 和 CSS,并显示网页内容和样式的小软件,效率高
②脚本解释引擎:解析并执行 Javascript 程序的小软件,效率略低
全球仅有四个独立的浏览器内核
浏览器 内核 内容引擎 脚本引擎
Microsoft IE Trident -- Chakra
Mozilla Firefox Gecko -- Monkey系列
Apple Safari Webkit Webcore Nitro
Google Chrome Webkit Webcore V8
Opera Presto -- Carakan
Opera(2013 -) Webkit Webcore V8
2、Javascript运行环境
运行环境:
①安装独立的Javascript解释器—Node.js
步骤:1、安装NodeJS
2、运行JS脚本:console.log ("输出的内容");
②浏览器内核嵌入的JS解释器:在console中输入脚本运行,将JS脚本嵌入在HTML网页中执行
_______________________________________________________________________________________________
输出位置(3个)
①向页面添加内容:<script>document.write("html代码段");</script> /*document:当前网页(不推荐)*/
②弹出对话框:弹出对话框显示消息:alert("提示消息"); /*弹出浏览器预定好的样式,不可修改*/
③向控制台中输出内容:F12→console.log("xx"); /*控制台专门用于调试程序,临时显示调试结果*/
书写位置(2处)
①页面的<script type="text/javascript"></script>标签中嵌入脚本
EX: <script>document.write("xxx");</script>
document.write:网页中打印输出一句话!里面的内容是交给内容排版引擎解析的
EX:docume.write("<h1>第一个JS</h1>");
一旦进入script标签内,就要使用js的语法
问题: 不符合内容与行为分离的原则,不便于维护和共用
②将脚本嵌入在外部的脚本文件中
1、创建脚本文件并编写JS脚本:创建一个**.JS文件;直接编写JS脚本
2、使用网页中进行引入:<script src="url"></script>
注意:必须成对出现,两个script标签之间不允许出现其他内容
放在<head></head>中,浏览器解析head部分时就会执行这个代码,然后才会解析页面其它部分
放在<body></body>中,浏览器读取到该语句时才会执行(一般使用此方法)
3、JS基本调试
JS运行过程中,如果出现错误,则终止本块的执行,但不影响后续代码块执行
<script></script>:代码块
4、基本语法规范
①代码的基本组成:语句
语句:允许被JS引擎所解释的代码,由表达式,关键字,运行符所组成
注意:严格区分大小写
所有的标点,全部都是英文的
字符串可以用" "或' '
语句都是以;表示结束
②JS中的注释:单行注释:// 多行注释:/**/
_______________________________________________________________________________________________
输出台操作(F12):
①Shift+Enter: /*仅换行暂不执行,用于多行输出*/
②console.log("Hello World!"); /*每写log一次,都自动换行*/
③左上角圆形叉号:Clear console /*清空控制台*/
④调出刚写过的代码段:上下键切换
调试程序:2种
断点调试:debugger; /*加在console.log 之前,在开着F12的情况下才有效*/
console.log(" , , "); /*在控制台输出(""中的+会将这两个变量视为字符串,最后一个不能加,)*/
启用严格模式:在script顶部插入:"use strict"; /*解决静默失败*/
严格模式下: 不用var定义变量是非法的,会导致错误;调用函数中的this值是undefined
非严格模式下: 不用var定义变量是全局变量;调用函数中的this值是全局对象
输入: prompt("输入提示") /*输入框: 专门请用户输入一个数据的对话框*/
_______________________________________________________________________________________________
变量和常量
变量
1、什么是变量:内存中存储一个数据的存储空间,再起一个名字,为了重用
量:数据
变量:变化的数据
内存:保存程序在运行过程中所需要用到的数据
变量:内存中的一段存储空间,用于保存数据
值:变量中所保存的数据
变量名:内存地址的别名即保存数据的空间的名称
2、变量的声明
①声明变量:在内存中,创建一个存储空间,再起一个名字
var 变量名;
默认值:undefined:专门表示一个从未使用过的变量
②为变量赋值:将数据保存在变量中(尽量不要让变量空着,赋初值)
变量名=值;
注意:只有等号才能改变变量中的值;等号会覆盖变量中的原值;变量赋值前必须先声明(给未声明过的变量赋值,普通情况下自动创建新变量并保存值;ES5模式规定禁止给未声明的变量赋值)
取用:取出变量中的值做运算,只要使用变量值,等效于直接使用变量中的值
不加引号的都会当做变量
③声明变量并赋值
var 变量名=值; /*只有等号才能赋值*/
注意:如果变量的值时非数字类型的话,要使用''或""括起来
声明时可以省略var关键字,省略后成为了全局变量,推荐不要省略var关键字
④推荐: 一条语句声明多个变量,用,分隔(每个变量必须要用=才能赋值)(建议多个变量换行写)
例:var 名1="xxx",名2="xxx",名3="xxx";
3、变量名的命名规范
①不允许是JS的关键字或保留关键字
②可以包含字母,数字,下划线(_),$
③不能以数字开头
④尽量见名知义
⑤可以采用“匈牙利命名法”,“驼峰命名法”,“下划线命名法”
驼峰命名法:变量名称,如果只有一个单词组成,采用全小写模式 例:var age
如果变量名由多个单词组成,第一个单词全小写,其余的每个单词的首字母,变大写
4、变量的使用
①变量定义后,未赋过值而直接使用
EX:var userName;
console.log (userName); 结果为:undefined,表示没有值
②对变量进行存取操作
1、获取变量的值-GET操作
例:var userAge=18;--------存值
console.log(userAge);------------取值
document.write(userAge);----------取值
user-----存值操作 18------取值操作
输出从未声明的变量时会返回:ReferenceError 没有找到对象
总结:只要变量没有出现在=左边,一律是取值
2、设置变量的值 – SET操作
例:var userAge=15;
var newAge=userAge
userAge---取值 newAge---存值
newAge=newAge+15;
console.log(newAge);--------30
总结:只要变量出现在=左边,一律是存值操作
笔试题: var a,b=2; → a:undefined b:2
var a=b=2; → a:2 b:2 (在函数中时,a是局部变量,b是全局变量)
_______________________________________________________________________________________________
常量
1、什么是常量
一经声明定义后,就不允许被修改的数据成为常量
目的:保证数据的准确性
适合用常量表示的数据:EX:1、圆周率:兀=3.1415926; 2、一周有7天
2、语法
const 常量名=值;
注意:①常量不允许赋值,否则会静默失败,ES5严格模式会报错
②声明变量时,必须初始化其值
③习惯上,常量名采用纯大写形式
取值:和变量用法一样
var 变量=prompt("提示") /*请用户输入变量的值,并保存在变量中,不能在node里使用prompt*/
_______________________________________________________________________________________________
数据类型(掌握)
1、什么是数据类型
保存在内存中数据的真实类型,约束了数据在内存所占的空间大小,存储结构
不同的数据类型,擅长执行的操作不一样,就需要配套合适的存储结构,给操作提供便利
2、数据类型分类
原始类型(基本数据类型: 值直接保存在变量本地的数据类型)
包括5个: number、string、boolean、null、undefined
引用类型: 值无法直接保存在变量本地的复杂数据类型
包括: Array、Function、Date、RegExp、Error、Object、String、Number、Boolean、Math、Window
数组是引用类型的对象,对象的本质就是关联数组,只不过用法更简单
函数名其实仅是一个普通的变量 ,函数其实是保存代码段的引用类型的对象
①number类型:
专门用于存储数字,表示32(8位一个字节)位的"整数",也可以标识64位的"浮点数",采用二进制存储(),凡是不加引号的数字直接量,默认都是number类型
何时: 如果一个数值可能需要比较大小和进行数学计算时
存储空间: 整数占4个字节,浮点数占8个字节,数值大小和存储空间无关(1字节=8位二进制)
特殊:舍入误差:计算机中也有计算不尽的数值
原因:number类型底层都是二进制存储
解决:四舍五入
n.toFixed(n)//四舍五入,保留n位小数,返回字符串类型,传入数字,可Number(x).toFixed(2)
typeof x / typeof(x) /*返回变量x中存储的数据类型*/
var m=n.toString(2) /*把n中的数值(先转为Unicode)转换为内存中的二进制形式*/
②string类型
什么是: 凡是加引号的一串字符直接量都是字符串类型,EX:姓名,性别,住址,身份证号,不用做计算和比较大小,都用""或''包裹
何时: 记录一串文字
js中一切文字都是由Unicode字符、数字、标点符号的序列组成的
Unicode 是编码(对全球主要语言的每个字编一个号)的一种,Unicode下所有的字符,每个字符均占2字节,而且每个字符都有一个独一无二的Unicode码
字母和数字占1个字节,汉字占2个字节
string类型的数据在使用过程中,要用""或''引起来
特殊字符需要转义,称为转义字符(字符串中具有特殊功能的字符)
如果在字符串中包含了和js语法冲突的','等,都要用\转义为普通字符
转义字符 表现(输出)形式
\n 一个换行
\t 制表符
\\ \
\" ''
\' '
例:var str= '你\n好';
路径:所有操作系统都支持/斜线,所以保存路径时要将\换成/:
var n=str.charCodeAt(i); //查看字符串str中下标i位置字符的unicode号
String.fromCharCode(unicode号) //将unicode号,反向转回文字,一次只能转一个字,要用循环
var m=n.toString(2); //将n中的数值转换为二进制形式
parseInt(10000000000,2); //把二进制数转换成十进制
var str=x.toString(); //将 x 转为字符串类型,不改变原值x。x为数组时,结果str用,分隔
x不能是null或undefined ——— 不是万能
var str=String(x); //将x转为字符串类型———万能(首选)
③boolean类型
作为条件的结果,来表示肯定(真)或否定(假)
何时: 只要作为判断条件的结论时,就用boolean类型
取值:true:真(肯定)
false:假 (否定)
例:var xxx=true;
该类型数据可以参与到数字的运算中:true = 1 false = 0
④undefined /⑤null
undefined:空,由程序自动为一个变量初始化之用;表示一个声明后未赋值的变量、没有返回值的函数
null:空,让程序员用于手动清空一个变量之用,表示一个空地址
第二章*****************************************************************************************
x:任何数据
str:字符串
num:数字
数据类型转换:(凡是从页面上获得的都是字符串)
作用:将不需要的数据类型,转化为需要的数据类型
js四大特点:弱类型的3大特点:
1. 声明变量时,不需要提前规定变量中存储的数据类型
2. 同一个变量先后可保存不同类型的数据
3. js会根据自身的需要,隐式转换数据的类型
何时:只要给定的数据类型不是想要的,都要转换
方法有2种:
1、隐式转换: 不需要程序员干预,由js自动完成的数据类型转换
何时: 只要给定的数据类型和js运算要求的类型不相符,js都会自动转化数据类型,再运行
如何:每种运算中都自带隐式转换
比如: 算数计算中
规则:
①默认:一切都转为number类型,再做计算
为什么: 因为number类型最适合计算
bool: true->1 false->0
②特殊:+运算中,只要碰到一个字符串,一切都转为字符串,+运算变为字符串拼接
若字符串左边有变量,先计算变量,从左到右依次计算(按优先级),到字符串的位置后,都转化为字符串
2. 强制转换:程序员主动调用转换函数实现的类型转换(3种情况)
何时: 只要给定的数据类型不是想要的,且自动转换的结果也不是想要的,就要强制转换
console.log(typeof x); /*输出str的数据类型*/
_______________________________________________________________________________________________
其他类型转number: 2种:
1. Number(x): 将纯数字x字符串或bool转为number类型(不直接修改原变量的值,而是返回新值)
x=Number(x); /*用于隐式转换中自动调用*/
何时: 都是隐式转换,其实相当于自动调用Number(x),很少主动使用
问题: 只能转换纯数字组成的字符串和bool类型
如果转不了: 就返回NaN
NaN: 代表一切不是一个数字的任何值:Not a Number
NaN参与任何运算结果只能是NaN
2. parseFloat/parseInt(str): 将字符串str转为number类型,可去除结尾非数字字符,但不去掉开头的,因为表达式从左到右依次执行,所以可以在计算后直接加个单位(首选parseFloat)
parseFloat可保留小数部分
parseInt 去掉小数部分(向下取整) //当使用e作为计数符号时,也会去掉e符号
何时: 只要将字符串转number,首选parseFloat(),Number()太局限
如果确实需要去掉小数,才选parseInt
如果转不了,也返回NaN
强调: 参数应该是string类型,如果给定的值不是string类型,则先执行隐式转换,转为string类型,再转number
Number/parseFloat/parseInt 都会自动去掉空格
特殊:
parseFloat("true") ->NaN
Number(true) ->1
Number("") ->0
Number(null) ->0
Number(undefined) ->NaN
其他类型转string: 2种:
1.var str=x.toString() 将 x 转为字符串类型,并返回结果。x为数组时,用,分隔
x不能是null或undefined ——— 不是万能
2.var str=String(x) 将x转为字符串类型——万能(首选)
其实,隐式转为string时,都是程序自动调用String
其他类型转Boolean类型: 1种
Boolean(x)
规则: 只有5个值会被转为false:0 "" NaN null undefined
其余都转为true
其实, 隐式转为bool时,都是程序自动调用Boolean(x)
_______________________________________________________________________________________________
运算符和表达式
程序: 人的想法在计算机中的执行
运算符: 程序中模拟人的想法的特殊符号
表达式: 由数据,变量和运算符组成的完成一项单一任务的语句
算数运算: + , - , * , / , %
%: 模运算/取余数: 被除数/除数,不要商,要除不尽的余数部分(取零头)
何时: 1. 取余数,可限制一个结果不超过指定的最大值
2. 判断能否整除
判断偶数: 能被2整除 n%2==0
判断奇数: 不能被2整除 n%2!=0
隐式转换
默认:都转number
特殊:+运算中,碰到字符串,都转字符串,+运算变为字符串拼接(在外面套一个parseFloat)
字符串左边的变量会先进行计算,遇到字符串全部转为字符串(按优先级,从左到右)
true在计算中为1,false为0;在字符串中为true/false
舍入误差: 计算机中,也有计算不尽的数值(如0.3-0.1, 0.1*3),一般是浮点型
解决:
1. 按指定位数四舍五入: n.toFixed(2)
今后几乎所有显示金钱数的地方都要toFixed(2)
2. 存储: 保存很长位数的小数: 0.39999999
关系运算: 用两个值做比较,做判断(若试图比较未定义的变量,会报错)
包括:> < >= <= == !=
返回值: bool 类型的true/fasle
隐式转换:默认都转为 number
特殊:1. 两个值都是字符串, 则不再转数字,而是依次比较两个字符串的每个字符unicode号
一个是字符串,一个是number,会进行隐式转换
2. 判断NaN:NaN和任何值做> < >= <= ==5种比较时,永远false
NaN和任何值做!=比较时,永远是true
问题:NaN==NaN =>false 用普通的==无法判断NaN
解决:isNaN(num) 专门代替==,用来判断num是不是NaN
何时: 只要判断是不是NaN,都用isNaN(num)函数
反用: 判断一个值是不是数字:!isNaN(num),若是数字,则返回true
注意: 空字符串、纯数字的字符串返回false(不是NaN)
3. 区分null和undefined
问题:==比较时,会自动将undefined隐式转为null
null==undefined => null=null
解决:=== 全等: 类型必须先相同,值再相等(!==,不全等同理)
其实===就是不带隐式转换的==
总结:
= 赋值,只有=可以改变变量中的值
== 自带隐式转换作比较
=== 不带隐式转换作比较
注意: 两个对象作比较,不做任何转换,直接比较两个对象的地址值(判断两个变量是否引用同一个对象)
逻辑运算: 将多个关系运算,综合起来得到最终结论
何时: 只要根据多个条件,综合得出最终结论时
包括:&&与(而且) ||或(要么) !非(没有)
条件1&&条件2...:
要求所有条件都为true,结果为true
只要一个条件为false,结果为false
条件1||条件2...:
只要一个条件为true,结果为true
除非所有条件都为false,结果才为false
!条件: 颠倒 条件的 判断结果
隐式转换: 默认将每个条件都转为bool类型
短路逻辑: 如果前一个条件已经可以得出最终结论,则后续条件不再执行
&&: 只有前一个条件为false时,后续条件才不执行
||: 只要前一个条件为true时,后续条件不再执行
利用短路:①简单分支结构: 1个条件,1件事,只有满足才做
如何: 条件&&(操作) (最简单的条件判断语句,注意加())
②利用||选择默认值,如果给定的值有效,则使用给定的值,否则使用默认值代替
如何:给定值||默认值
无效:只要给定的值为0 "" NaN null undefined
注意:如果逻辑运算最后执行的是一个关系运算,则返回bool
如果逻辑运算最后执行的是一个值,则返回值,而不返回bool
_______________________________________________________________________________________________
位运算: 了解
用二进制简化普通十进制的计算或操作
1. 左移/右移:
m<<n m左移n位,相当于m*2的n次方
m>>n m右移n位,相当于m/2的n次方
1<<3=1*2³=8
2<<3=2*2³=16
8>>3=8/2³=1
2. 取整:
n^0 n|0 n>>>0 代替/简化Math.floor(n),用来把n向下取整(^ 按位异或)
3. 交换两变量的值:
var a=3,b=5;
方法一: var t=b; b=a; a=t;
方法二:a+=b; b=a-b; a-=b;
方法三:a^=b; b^=a; a^=b;(二、三只能交换number类型的数据)
方法四: a=a+b; b=a-b; a=a-b;
赋值运算:
扩展赋值运算: 对特殊赋值运算的简化
何时:只要取出变量中的值,计算后,再存回原变量中
a=a+b 将a的值+b的值,再存回a中
将b的值累加到a上:可简写为a+=b
a=a+b -> a+=b;
a=a-b -> a-=b;
a=a*b -> a*=b;
a=a/b -> a/=b;
a=a%b -> a%=b;
更简化: 递增递减运算: 如果每次累加1/累减1
a+=1 -> a++
a-=1 -> a--
前++和后++
1. 如果单独使用, 前后都一样
2. 如果参与到其他表达式中时:
相同:变量中的值一定都会变化,+1
不同: 前++,使用返回+1后的 新值去运算
后++,使用返回+1前的 旧值去运算
注意:所有表达式都从左到右依次执行;先执行的操作会影响后续操作
函数中: return i++; 返回+1前的 旧值去运算
注意: ++a并不总和a=a+1完全一样,++运算符不会进行字符串连接操作,它会先将操作数转换为数字并增1
比如: var a="1"; ++a为2, a+1为字符串"11"
第三章*****************************************************************************************
一、函数类型
定义: 内存中封装一项任务步骤清单的代码段,再起一个名字
为什么:代码重用、划分功能
何时: 只要一段代码,可能被反复使用,就都要先封装在函数中,再反复调用函数
如何: 分2步
1、声明(两种方法)
①function函数名(参数变量列表){ /*形参*/ /*function创建函数*/
函数体(代码段);
return 返回值; /*返回值要接住,再输出才能显示*/
}
② 函数名=function(参数变量列表){
函数体(代码段);
return 返回值;
}
参数: 函数运行时,接收传入函数的数据的变量。参数用法和普通变量完全一样,只不过不用var声明
参数列表: 多个参数间用逗号分隔(参数变量1,参数变量2...)
何时:若一项任务必须某些数据才能正常执行时,就必须定义参数
作用:①提醒调用者正确使用函数;②让函数变得更灵活
返回值: 函数执行的结果(由是否需要返回结果决定是否返回值)
何时: 如果函数的调用者需要获得函数执行结果
如何返回: return 返回值;
作用:①return可单独使用: 退出函数;②退出函数时,顺便返回结果
如果没有返回值的函数,就会默认返回undefined
2、调用: 让引擎按照函数的步骤清单,执行任务
var 返回值=函数名(参数值列表);
或 函数名(参数值列表); /*实参*/
何时: 函数只有调用才执行,不调用不执行
参数值列表: 传入函数的执行时必须的数据列表
只要函数定义时规定了参数变量,调用时都要传入参数值,且顺序和个数保持一致
每个参数值之间用逗号分隔
_______________________________________________________________________________________________
作用域scope: 一个变量的可用范围
为什么:避免不同范围的变量之间互相污染(注意执行顺序)
包括: 2种:
1.全局作用域: window(保存着全局变量)
什么是: 程序中的任何位置都可以访问的范围
全局变量: 保存在全局作用域中,程序任何位置都可使用的变量
特点:随处可用,可反复使用
何时: 如果一个变量需要反复使用,或跨函数随处可用时,只要不属于任何函数的变量,都是全局的
用法:console.log(变量名);
2.函数作用域:(保存着局部变量)
什么是: 仅函数内可用的范围
局部变量: 保存在函数作用域中,仅函数内可用的变量
特点:仅在函数内可用,不可重用
何时: 如果只限于当前函数内使用,函数外不可用时
如何:1.函数的参数变量
2.在函数内用 var 声明的变量
总结: 优先定义并使用局部变量
尽量少使用全局变量——避免被污染
变量的使用顺序:优先使用函数内的局部变量,局部没有才去全局找
声明提前(hoist,提起):
什么是: 在开始执行程序前,引擎会将var声明的变量和function声明的函数,提前到"当前作用域"顶部集中优先创建,再开始执行程序 /*但是赋值留在原地 */
笔试: 如果先使用,后声明,一定在考声明提前,就要将所有var和function提前到当前作用域的顶部,先创建,再判断程序的输出
问题: 破坏了程序默认的执行顺序
解决: ①传统: 强烈建议将所有的声明都集中在当前作用域顶部
②ES6: let代替var声明变量
let禁止在声明之前,提前使用该变量,强制将声明集中在当前作用域顶部创建
限制:不能用let反复创建相同名称的变量
函数声明:
var/let 函数名=function(参数变量列表){...} /*用这种方式创建的函数不会被声明提前*/
本质: 函数名其实仅是一个普通的变量
函数其实是保存代码段的引用类型的对象
函数名通过函数对象的地址引用着函数对象
按值传递:
什么是:两变量间赋值,或将变量传入函数作为参数时,其实只是将原变量中的值复制一个副本给对方
结果:原始类型的值会 修改新变量,不影响原变量的值
_______________________________________________________________________________________________
2. 全局函数(了解)
什么是: ES标准中规定的,浏览器已经实现的,不需要任何对象(前缀.)就可直接调用的函数
比如: String()/Number()/Boolean()
parseInt/parseFloat()
isNaN()/encodeURI/decodeURI
反例(省略了前缀,属于BOM): alert()/prompt()...
编码解码: 特指对地址栏中的url内容进行编码和解码
什么是编码: 将url中多字节字符或保留字符编码为单字节字符
为什么: url中不允许出现多字节字符以及和保留字符冲突的字符,否则会乱码
何时: 只要url中可能包含多字节字符以及和保留字冲突的字符时,都要先编码为单字节
什么是解码:将编码后的单字节字符串解码回多字节原文
何时:只要收到的是编码后的字符串,都要先解码再使用
如何:编码: var code=encodeURI(url);
解码: var url=decodeURI(code);
问题: 不能对保留字符编码解码,比如: : /
解决:编码: var code=encodeURIComponent(url);
解码: var url=decodeURIComponent(code);
注意: 不会对ASCII字母和数字进行编码,也不会对ASCII标点符号进行编码: - _ . ! ~ * ' ( ) 。
其他字符(比如: ;/?:@&=+$,# 这些用于分隔URI组件的标点符号),都是由一个或多个十六进制的转义序列替换的
eval函数: 执行一段字符串格式的js表达式
eval()的作用
把字符串参数解析成js代码并运行,并返回执行的结果
eval的作用域:
作用域在它所有的范围内有效,但是IE8及以下指向window(全局)
解决方法:
functiona(){
if(window.execScript){ // 支持IE8及以下的版本
window.execScript("var x=1");
}else{ window.eval("var x=1"); } //常用的浏览器都支持
console.log(x);
}
a();
console.log(x);
execScript与eval区别:
相同点:
execScript与eval都可以接收一个字符串,若该字符串是表达式(expression),则执行时将求得该表达式的值并返回;若该字符串是一个或多个语句(statements),则执行时将运行这些语句
不同点:
① execScript是IE浏览器独有;eval则是所有浏览器都支持
② execScript无论是在什么作用域(global/local)内被调用,它所接受到的表达式(expression)或语句(statements)字符串都将在全局作用域内执行(global);eval则是在它被调用时所在的作用域内运行它所接受到的表达式(expression)或语句(statements)字符串
在不支持execScript函数的浏览器下实现在全局作用内执行字符串
function globalEval(data){
if(data){
(window.execScript || function(data){ window["eval"].call(window, data); })(data);
}
}
_______________________________________________________________________________________________
程序三大结构: 顺序(判断,不循环),分支和循环
1、分支结构
什么是: 让程序根据不同的条件执行不同的操作
何时: 只要让程序根据不同的条件执行不同的操作
如何:
1. 一个条件,一件事,满足就执行,不满足就不执行
如果操作简单: 短路:条件&&(操作1,操作2,操作3...)
如果操作复杂:
if(条件){
操作1;
操作2;
...
}
2. 一个条件,二件事,二选一执行:
如果仅两个值二选一:
条件?值1:值2
如果操作简单: 三目运算/三元运算/条件运算(三目运算符的优先级低于+)
条件?操作1:操作2 /*满足条件执行并返回操作1的值,不满足则执行并返回操作2的值*/
如果操作复杂:
if(条件){
操作1; /*满足条件执行*/
}else{
操作2; /*不满足条件执行*/
}
3. 多个条件,多件事,多选一执行(嵌套)
如果多个值,多选一: 三目运算(一般对齐)
条件1?值1:
条件2?值2:
...?... :
默认值 /*强调: 默认值不能省略*/
如果操作简单: 三目运算
条件1?操作1:
条件2?操作2:
...?... :
默认操作 /*强调:默认操作不能省略*/
如果操作复杂:if...else if结构
if(条件1){
操作1 /*如果当前条件满足,则不再向后执行*/
}else if(条件2){ /*如果进入条件2,暗示条件1不满足*/
操作2
}else if(...){
...
}else{ /*如果没有默认操作,则else可省略,即什么也不做*/
默认操作
}
简写:如果if(...)一句话 else(...)一句话 后面只有一句话,可省略{}(if、else仍然要写)
特殊: 如果所有条件都是等于比较,可简写为
switch(表达式){ /*先计算表达式的值,用表达式的值和每个case后的值做"全等==="比较*/
case 值1: /*如果表达式的值全等于case后的值1*/
操作1; /*就执行操作1*/
case 值2:
操作2;
...
default: /*如果所有case的值都不等于表达式的值*/
默认操作; /*则执行默认操作*/
} /*强调: 最后一个default可省略*/
问题: 只要前一个case满足条件,则后续所有case都被执行(而不会再判断)
原因: switch是入口
解决: break;可终止当前结构继续向后执行,并退出switch
如何:每个case之间,都要加break;
判断一个值是否为空可以直接用if(值){ },不加等号,判断是否为true
第四章*****************************************************************************************
2、循环loop
什么是: 让程序反复执行相同的代码段
何时: 只要让程序反复执行同一段代码
如何: 三要素:
1. 循环条件: 让循环可以继续执行的条件(只要条件满足就反复执行循环,直到不满足时退出循环)
2. 循环变量: 在循环条件中用作比较和判断的变量
从几开始, 每次递增/递减几,到几结束
3. 循环体: 循环要反复执行的代码段
几乎都要修改循环变量,直到不满足条件;若循环条件始终为true,则循环永远无法退出---死循环
包括: 3种:
while:
var 循环变量=初始值; /*声明并初始化循环变量*/
while(循环条件){ /*当满足循环条件时*/
循环体;
修改循环变量;
}
何时: 必须先满足循环条件,才能执行循环体时
do...while:
var 循环变量=初始值;
do{
循环体;
修改循环变量;
}while(循环条件); /*当满足循环条件时*/
何时: 即使条件不满足,也至少可以执行一次时(先执行,再判断)
while VS do...while
如果第一次循环都满足,两者的输出是完全一样的
while: 先验证条件后执行
do...while: 先执行一次,再验证条件
如果第一次条件不满足,则while是一次都不执行,do while至少执行一次
for:
for(var 循环变量=初始值;循环条件;修改循环变量){
//循环条件中有,时(逗号表达式),以最后一个为准
循环体; /*先执行循环体,再修改循环变量*/
}
for循环和while循环的原理是完全一样的(就是while循环的简化)
for vs while: 如果循环变量的变化有规律: 首先for
如果循环变量的变化没有规律: 首先while
强调:JavaScript中没有块级作用域
放在if/else if/else/for/while中的变量,出了块(结构),依然可用
c、c++、java等所有{}都认为是块级作用域,块中的变量出了块,不能使用
解决: 让循环中的变量不要泄露到循环外
用let代替var: let声明的变量仅能在{}内使用
简写:var 可同时声明并初始化多个变量,用,分隔
如果for循环下只有一句语句,可省略{}—————不建议,容易出歧义
如果for循环体中只有一句话,且很简单时,for循环的修改循环变量中可先后执行多个短小的操作,每个操作之间用逗号(,)分隔,省略循环体并加分号(;)结束——但不能改变原来的执行顺序
_______________________________________________________________________________________________
break(中断) VS continue(跳过):
break: 中断并退出当前循环
何时: 当判断条件非常复杂时,就可用死循环+break的方式灵活控制循环退出——降低循环编写的难度
continue: 跳过本轮循环,继续执行下一轮
只要颠倒判断条件,就可避免使用continue
强调:break不能参与到任何简写中,必须独立一句
嵌套循环: 循环内,又执行了另一个循环
步骤: 1. 截取片段找规律
2. 用外层循环反复调用规律的公式
_______________________________________________________________________________________________
二、数组类型
什么是: 内存中连续存储多个数据的一块存储空间,再起一个名字
为什么: 便于维护和查找
程序=数据结构+算法
数据结构: 数据在内存中的存储结构
算法: 解决问题的步骤
好的数据结构可极大提高程序的执行效率
何时: 今后只要保存多个同一类型的数据时,都必须用数组
如何: 3件事(创建、赋值、取值)
创建: 3种:
1.创建空数组2种:
何时: 创建数组时,暂时不知道数组内容
var arr=[]; /*[]创建数组*/
var arr=new Array();
2. 创建数组同时初始化数组内容:
何时: 创建数组时已知数组的内容
var arr=[值1,值2,...];
var arr=new Array(值1,值2,...);
3. 创建n个空元素的数组(只有一种):
何时: 创建数组时,只知道数组元素个数,暂时不知道数据的内容
var arr=new Array(n); //()里若只有一个数字,创建空数组,否则设置其为数组的内容
访问:
元素:数据中每个数据,都称为元素
下标(index): 每个元素的存储位置的序号。默认都是数字,从0开始,连续不重复
赋值: 将数据保存到数组的某个元素中
arr[i]=新值; /*i:下标index*/
取值: 数组中每个元素的用法和普通的变量完全一样
数组也称为一组变量的集合,起一个统一的变量名
arr[i]
console.log(arr[i]); /*输出数组下标为i的元素*/
console.dir(arr); /*查看内存中arr的结构和内容*/
dir问题:不会立刻输出结果
只有手动点击三角时,才动态查找内存中对象的最终结构,会打乱程序的输出结果顺序
解决: 如果想查看数组中间状态的内容:
console.log(String(arr)); /*对数组拍照*/
js的数组三个不限制:
1. 不限制元素的数据类型
2. 不限制下标越界:
赋值时越界: 不会报错!在指定的新位置自动创建新元素保存新值(添加后,数组的元素下标不连续则称为稀疏数组)
取值时越界: 不会报错! 仅返回undefined
3. 不限制元素个数: 在任何时候,在任何位置添加新元素
.length属性: 记录数组中理论上的元素个数(不一定和实际元素个数相符)
特点:.length 永远等于最后一个数字下标+1(自动维护,不需要手动修改)
.length 永远指向最后一个元素的下一个新位置
.length可修改数组大小——缩容(如使arr.length=5,可获取数组的前5个值)
用法注意:arr.length /*.length属性属于数组,不能脱离数组单独使用*/
固定套路: 1. 获取数组最后一个元素:arr[arr.length-1]
2. 获得倒数第n个元素:arr[arr.length-n]
3. 末尾追加一个新元素:arr[arr.length]=新元素
4. 删除数组最后一个元素(改小length) :arr.length-=1;
5. 删除数组末尾倒数n个元素(改小length):arr.length-=n;
_______________________________________________________________________________________________
数组是引用类型的对象
原始类型的值: 修改新变量,不影响原变量—————按值传递
原始类型:基本数据类型:值直接保存在变量本地的数据类型,Number/String/Boolean/Undefined/null
原因:将原变量中的实际值复制一个副本给对方
引用类型的对象: 用新变量修改对象,等效于直接修改原对象。新旧变量都受影响(arr2=arr1)
引用类型:值无法直接保存在变量本地的复杂数据类型
原因:仅将原变量中的地址值复制给新变量,导致两个对象共用同一个对象
新旧变量使用相同的地址值,引用同一个对象(地址值相同)
遍历:
什么是: 依次对数组中每个元素执行相同的操作
何时: 只要对数组中每个元素执行相同的操作时
如何:循环
for(var i=0;i<arr.length;i++){
arr[i] /*当前元素*/
}
var i=0,len=arr.length; i<len; i++ //可使用缓存代替arr.length,减少延迟,提高性能