JavaScript知识点总结

2,028 阅读21分钟

愿你被这个世界温柔以待

JS代码原则:高内聚,弱耦合

  1. ecmascript是一种语言标准,第一版标准发布于1997年,javascript是网景公司对ecmascript标准的一种实现。

  2. js不区分整数和浮点数,统一用number表示,nan表示 not a number,无法计算结果的时候用nan表示。

  3. 字符串string,是以单引号或者双引号括起来的任意文本,比如'abc',"abc".

  4. 布尔值boolean,布尔值只有两种值,true或者false。

  5. &&与,||或,!非。

  6. 编程形式的区别:面向对象、面向过程

  7. typeof:六种数据类型:number string boolean undefined object function typeof返回的是对象的两个object:null和{}

  8. 浏览器组成

    shell部分

    内核部分

    渲染引擎(html和css基础语法识别、语法规则和渲染)

    js引擎

    其他模块

  9. js特点 js是解释性语言(浏览器读一行翻译一行,php/python也是解释性语言) 优点:跨平台、单线程(异步传输数据:) 不足:速度较慢

  10. js标准 标准是由ecma制定的 所以有时候也叫ecmascript 延申两个部分dom bom js三大部分:ecmascript、dom、bom js执行队列:单线程,解释性语言,异步传输

  11. 前端开发要求:结构(html)、行为(js)、样式(css)相分离

  12. js变量(声明变量的只有var,浮点型) 变量命名规则:必须以英文字母、下划线和$开头;变量名可以包含英文字母、下划线、$及数字;不可以用特殊语法(关键字)和保留字作为变量名;

数据类型:

常见的数据类型:number string Boolean undefined object function

引用值和原始值唯一的不同是赋值形式不同
原始值:number boolean(true是1,false是0) string(字符串)  undefined(变量没有赋值)  null(表示占位,值为空)属于object类型
存放地方不一样
原始值是存放在栈(stack)里面的
“先进后出”
引用值和原始值唯一的根本区别是赋值形式不同。
原始值是不可改变的,一个房间已经写了一个值,不可以改变。

删除数据的时候并不会删除数据在内存中的位置,只是让数据包的编号名字与该数据不对应,无从查找,但是依旧存在在内存中。只能二次覆盖。

栈内存之间的赋值是拷贝,互相不影响,定义的进去的值不可改变

var z = 10;
var x = z;
z = 20;
document.write(x);
//输出的x值是10;
引用值:array object function data regexp
引用值是存放在堆(heap)里面的
引用值拷贝引用值拷贝过去的是地址
var arr = [1,2];
var arr1 = arr;
arr.push(5);
document.write(arr1);
//输出值为 1 2 5

基本语法

一行结束必须添加分号;程序读取代码一行是识别分号,(函数function for循环 if之后不需要加 ;(分号) function for循环 if判断语句 )

任何符号的两侧必须要有一个空格

错误分为两种

低级错误:

不可以写中文字符,语法解析错误

控制台会显示如下:

uncaught syntaxerror: invalid or unexpected token:

js运算符

0/0 = NaN,0%0 = NaN

1%0 = NaN,-1%0 = NaN

1/0 = infinity infinity是数字类型的 number

-1/0 = -infinity +:数字运算、字符串连接(隐式转换两边都是字符串);

任何数据类型加字符串都等于字符串(隐式转换 + )

%:取余

var rr = 3;
rr %= 4;
document.write(rr);
//输出的值是3

// 调换aa bb的值
var aa = 123;
var bb = 234;
var temp = aa;
aa = bb;
bb = temp;
document.write(aa);
document.write("<br>");
document.write(bb);

Boolean:false和true 字符串比较的是asc码的顺序

逻辑运算符

&&(与):(与 是碰到假就返回当前的值)

先看第一个表达式转换成布尔值结果,如果结果为真,那么它会看第二个表达式转换为布尔值的结果,然后如果只有两个表达式的话,那么看到第二个表达式,就可以返回该(第二个)表达式的值了。

var a = 1 && 2 + 2;返回的值为4,因为第一个先看var a = 1的值是否为真,在该例子中为真,则返回&&后面的(最后一个值)计算结果4;

返回结果为false的:undfined,null,NaN,“ ”,0,false。

var a = 0 && 2 + 2;返回的值为0,因为第一个是假,直接返回第一个值。

var a = undefined && 2 + 2;返回值为undefined。

&&升级:中断作用,短路语句:检查该语句是否存在错误或者能否执行。

data && function(data);如果data返回false则表示data数据不存在或者错误。

||(或):(碰到真就返回当前的值)

||或运算符经常用于实现解决浏览器的兼容问题

!(非):

for循环的执行顺序:

for (var i = 0; i < 10; i ++)

  1. var i = 0;
  2. if(i < 10){} 条件判断
  3. i ++
  4. if (i < 10){}
  5. i ++
  6. if(i < 10){}

条件语句

if和else直接的语句必须是互斥的,满足条件1 一定不满足其余条件。

i++先使用i,再进行计算i = i + 1;

小练习:

计算2的n次幂,n可输入,n为自然数:

var n = parseint(window.prompt(“input number”));
//先定义一个mul的初始值
var mul = 1;
for(i = 1;i <= n; i++);{
//2的n次幂
//2的一次幂代表1乘以一个2
//2的二次幂代表1乘以2的值再乘以一个2
mul *= 2;
}
document.write(mul);  

计算n的阶乘,n可输入

var n = parseint(window.prompt(“input a number”));
var jiemul = 1;
for(var i = 1;i <= n; i ++)
{
jiemul *= i;
}
document.write(jiemul);  
输入a,b,c,三个数字,打印出最大的
//因为要输入三个数,所以要写三个parseint
var a = parseint(window.prompt(“input a”);
var b = parseint(window.prompt(“input b”);
var c = parseint(window.prompt(“input c”);
if(a > b){
if(a > c){
document.write(a);
}
else{
document.write(c);
}
}
else{
if(b > c){
document.write(b);
}
else{
document.write(c);
}}

条件语句

输入星期时,显示工作或者休息

var date = window.prompt('input');
switch (date) {
	case "monday":
	case "tuesday":
	case "wednesday":
	case "thursday":
	case "friday":
		console.log('working');
		break;
	case "saturday":
	case "sunday":
		console.log('relaxing');
		break;
}

typeof操作符:

可以返回6个值:number string Boolean object undefined function 显示类型转换:

Number:将输入的内容转化成数字

String:将输入的内容转化成字符串:

var demo ="123.3";
var num = String(demo);
console.log(typeof(num) + ":" + num);

隐式类型转换:

逗号操作符:英文的,

例如:1,2的返回结果就是逗号后面的值为2,始终返回最后一个逗号后面的值


console.log(isNaN("abc"));
//输出true:隐式转化
console.log(isNaN(null));
//输出false
//false是0,true是1

类型转换

显示类型转化和隐式类型转换

number:将变量值转化成数字,null可以转换成0,true是1,false是0,但是一个是特殊的,undefined被转换成数字类型,会输出:nan.看起来不是数字的也是输出nan,如果是“123abc”也是被转换成NaN,不能转换成具体的数字。

parseint:把内容转换成整型的数,就是整数,输入123.98,会直接舍去,输出123,输入“123abc”输出“123”,parseint有个独特的功能,从数字位开始往后看,一直看到非数字位截止,把之前的数字返回。

parsefloat:更parseint很相似,不同的是,float是浮点数就是小数,如果输入内容是:“123.45abc“,会输出123.45,它也是从数字位开始看,一直看到除了.之外的非数字位截止,后面的做截断,返回前面的值。 string:把内容转换成字符串,

boolean:把内容转换成布尔值,输入0 -0 null undefined nan false以及空字符串” ”会输出false,其余的均输出true。

tostring:想把谁转换成字符串就用谁.tostring,有两个特殊的,undefined和null不能使用tostring这个方法。

隐式类型转换:

isNaN()-->(调用的是Number):把变量拿出来,先放到number里面去,转换的结果再与nan 比对,如果是NaN则打印出true,如果不是则输出false.这个数必须是NaN的时候才返回true,例如isNaN(‘100’),显然100不是NaN,则返回false

++/--、+(正) -(负)(调用的是number)

-(减号)*/% --》number(调用的也是number)

+(加号)(调用的是string):有一个特殊的语法,当加号两侧有一个是string(字符串),就会调用string将两个全部转换成字符串。例如:var num = (1 + '2');输出的是12,因为+加号已经将1转换成字符串“1”,所以结果是12.

< > <= >=(转换成boolean) :var num = 1 > "2";打印出false。

== !=(调用的也是boolean): undefined == null;打印true,undefine和null一样,> = < 0都会输出false。

不发生类型转换(左右两侧长得一模一样(类型和数字)才会绝对等于,除了NaN) ===:绝对等于 !==:绝对不等于

注意:typeof(a)返回的是字符串”undefined”,所以typeof打印出的结果类型是string。

小练习:

此处注意:NaN不等于NaN,但是undefined == null;

函数:

  1. 定义:function 函数名(){}函数名和变量名格式差不多, 但是命名必须符合小驼峰原则:单词首字母小写,后面单词的首字母必须大写。
  2. 函数组成形式: 函数名称、参数(形参、实参arguments)、返回值。不定参数、
  3. 函数的作用域:(函数里面的参数,就相当于函数内部已经定义好了的变量)

JS(单线程、解释性语言)运行三部曲:

语法分析、预编译、解释执行

arguments.length 表示实参的个数,函数名.lenth表示形参的个数。

js预编译:

函数声明整体提升

变量 声明提升(注意只是声明提升,并不是赋值提升)

imply global:暗示全局变量,

全局对象:window

window就是全局的域:

var a = 123;

等于先声明var a;再a = 123;

console.log(a);

window相当于仓库,是一个对象和GO(global object)一样的功能。

任何全局变量都是window的属性

预编译:一切声明的全局变量(注意不包括局部变量),全是window的属性。

window 就是全局,

预编译发生在函数执行的前一刻:

预编译的步骤:
第一步:创建AO (activation object)对象。执行期上下文,就是理解的作用域

第二步:找函数的形参和变量声明,将变量声明的名和形参作为AO对象数属性名,值为undefined

第三步:将实参值和形参值统一

第四步:在函数体里面找函数声明(定义一个变量等于函数不算函数声明(var a = function(){}),函数声明必须有函数名才可以),值赋予函数体
预编译声明的变量或者函数输出的时候,如果有自己的AO值,就打印输出自己拥有的AO的值,就近原则,而不必要打印输出GO就是window的值。

作用域:

[[scope]];存储了运行期上下文的集合

作用域链:scope所存储的执行期上下文对象的集合

查找变量:从作用域链的顶端依次向下查找。

补充一点:在哪个函数里面查找变量,就取函数的作用域链的顶端依次向下查找。

闭包:

如果内部的函数被保存到外部,它一定生成闭包。

缺点:闭包会导致原有作用域链不释放,造成内存泄漏

内存泄漏:内存占用多了,可利用的内存就少了。

闭包的作用

实现公有变量:函数累加器

可以做缓存:存储结构

可以实现封装,属性私有化

模块化开发,防止污染全局变量

闭包:内部函数在外部被调用的时候产生闭包,只有闭包才可以实现在外部调用和改变内部函数的属性

对象: 增删改查

对象创建方法:

1、var obj = {} plainObject    //对象直接量
2、构造函数创建方法
1)系统自带的构造函数new Object() Array() Number()
2)自定义 构造函数命名的时候首字母都要大写
构造函数的内部原理(三段式)
1、	在函数体最前面隐式的加上this = {}
2、	执行 this.xxx = xxx;
3、	隐式的返回this
只有对象才有属性和方法,对象包括函数、数组和对象自己。

var str = new String (‘ass’)

在函数前面加了一个new,就是一个构造函数

undefined和null不可以设置属性

原始值数字不可以有属性和方法,但是对象可以有属性和方法。

原始值不能调用属性和方法

原型:function对象的一个属性,定义了构造函数制造出的对象的公共祖先,通过该构造函数产生的对象,可以继承该原型的属性和方法,原型也是对象。

构造函数名字.prototype.属性 = 值。

提取公有的部分写到原型内,减少代码的冗余,

object.prototype是原型链的终端。

原型链的原理和原型差不多,增删改查也差不多

修改:如果属性有引用值的时候,就可以修改

Object.create也可以创建对象

绝大多数对象最终都会继承自Object.prototype,并不是所有的对象继承最终都会来自这个。

原型是系统自定义的内部属性,不可以自己添加。

只有undefined和null没有toString和原型

toString:变成字符串形式,本身没有方法,要包装类

Math:ceil:向上取整:

Math:floor:向下取整:

math:random();产生0到1的开区间随机数(0,1)

toFixed(n):保存n位有效数字,是保留小数点之后的有效位数为n,如果是个整数的话,则小数点之后是两个0

如果保留两位有效数字的时候,小数点之后的第三位数字大于等于5的时候就要进1.

注意:call/apply:改变this指向

在企业上的实际运用就是借用别人的函数实现自己功能

call和apply的区别:apply只能传入一个实参,且必须是数组

call和apply的目的是改变this的指向

两者的区别是传参列表不同。(call 需要把实参按照形参的个数传进去(就是实参个数==形参个数),apply 需要传一个arguments 实参列表)

继承发展史.

  1. 原型链
  2. 借用构造函数
  3. 共享原型
  4. 圣杯模式

this:(很重要)

  1. 函数预编译过程中,this指向—> window,预编译的时候arguments是放在AO的,且还有一个this:window,var this = Object.create(funxtion.prototype);
  2. 全局作用域里面:this -- > window,就是GO里面也有一个this:window。
  3. call/apply可以改变函数运行时this指向,两者的区别是传参列表不同。
  4. obj.func();func()里面的this指向obj(谁调用的这个方法,这个方法里面的this就指向谁) 命名空间 管理变量,防止污染全局,适用于模板化开发 类数组: 组成部分:属性要为索引(数字)属性,必须有length属性,最好加上push方法, 属性一旦经历了var的操作,所得出的属性,这种属性叫做不可配置的属性。 通过var增加的属性,叫不可配置的,不能删除 1、预编译 this --> window 2、谁调用的this指向谁 3、call apply 4、全局 this --> window
  5. try catch 在try里面发生错误,不会执行try里面的后续代码,然后执行外面的 try里面的代码有错的时候,后续的代码还是可以执行的 错误信息

evalError:eval()的使用与定义不一致

rangeError:数值越界

常见的:

referenceError:(未经声明(变量、函数)就使用 is not defined)

syntaxError:语法解析错误(代码中出现中文字符)

浏览器是基于es3 + es5新增的方法

“use strict”,在代码最顶端加上就变成了es5

和es3产生冲突的解决方案,均使用es5的

es5的严格模式不能用with

with会把里面的对象当作with要执行的代码体的作用域链的最顶端

with可以改变作用域链,with里面的对象是AO

with可以简化代码

es5规定变量赋值前必须声明

局部的this必须被赋值,赋值是什么就是什么

局部的this预编译的时候是空值,不赋值会是undefined

es5不可以重复属性和参数,但是不报错

eval里面能够将字符串当作代码执行

DOM

document object model(操作html)

对html的标准编程接口

dom的基本操作:

获取键盘码:

document.onkeydown = function(e) {console.log(e.which)};

选中页面的一个元素,按键盘上面的键

键盘的操作:上38,右39,下40,左37,enter:13,空格:32,删除:8

立即执行函数:

for循环里包含有不知道什么时候执行的函数,并且这个函数访问了for的循环变量,就要使用立即执行函数函数解决 i 被改变成最终值的问题 sublime 按照插件:

emmet教程

首先安装package control

再preferences ----> packsge control安装,安装完了之后打开输入install package ----> 输入emmet安装 ---》 输入jsprettify安装。

dom基础操作

document代表整个文档

查看元素的节点:

document.getElementById

document.getElementsByTagName(比较常用)

document.getElementsByClassName

document.getElementByName 只有部分标签name才可以生效(表单、img、iframe) 基本不用

querySelector:基本不用,选出来的元素不是实时的,

遍历树节点

parentNode -> 父节点(最顶端的parentNode是#document)
childNodes -> 子节点们
firstChild -> 第一个子节点
lastChild -> 最后一个子节点
nextSibling –> 后一个兄弟节点 
previousSibling -> 前一个兄弟节点

节点的类型: 元素节点(1)、属性节点(2)、文本节点(3)、注释节点(8)、

基于遍历元素节点树的遍历

parentElement -> 返回当前元素的父元素节点(ie不兼容)
children -> 只返回当前元素的元素子节点(常用)
node.childElementCount === node.children.length当前元素节点的字节点
firstElementChild ->返回第一个元素节点(ie不兼容)
lastElementChild ->返回最后一个元素节点
前一个兄弟元素节点:
nextElementSibling:
最后一个兄弟元素节点
lastElementSibling

节点的四个属性:

nodeName:元素的标签名,以大写的形式表示只读

nodeValue:文本或者注释comment节点的属性,可以读写

nodeType:只读,不可写入(任何元素都有这样一个属性)

attributes:element节点的属性节点的结合(能够赋值和修改) 节点的一个方法:Node.hasChildNodes()有没有子节点,代表一个函数方法,所以必须要加括号

类数组加一个splice:Array.prototype.splice之后就是一个数组 Document可以理解成构造函数,document代表整个文档

两者之间是逐步继承的关系

document –- > HTMLDocument -- >Document.prototype

HTMLDocument.prototype  {proto:Document}

document上面有两个直接的属性,一个是body一个是head

document.documentElement --- >指的就是html JS三个组成部分

ecmascript dom bom

基于元素节点树的遍历,除了children之外,兼容性比较差

构造函数都有一个原型

dom结构树,一系列的继承关系

就近继承

date对象

var date = new Date()

date.getTime(),距1970年1月1日的毫秒

setInterval是非常不准的,定时器,是window上面的一个方法

setTimeout只执行一次

查看视口的尺寸

window.innerWidth/innerHeight (加上 滚动条宽度 / 高度)
IE8及IE8以下不兼容
document.documentElement.clientWidth/clientHeight
标准模式下,任意浏览器都兼容
document.body.clientWidth/clientHeight
适用于怪异模式下的浏览器
封装兼容性方法,返回浏览器视口尺寸getViewportOffset()

查看元素的位置

dom.offsetLeft, dom.offsetTop

对于无定位父级的元素,返回相对文档的坐标。对于有定位父级的元素,返回相对于最近的有定位的父级的坐标。(无论是 left 还是margin-left等都是距离。 )

position的默认值:static

dom.offsetParent

返回最近的有定位的父级,如无,返回body, body.offsetParent 返回null emmet: ul>li{$}*5

____滚动条在y轴上滚动的距离 + 浏览器的视窗高度 = 文档的总高度 当 :滚动条在y轴上滚动的距离 + 浏览器的视窗高度 = 文档的总高度 说明:已经滚动到底部 ____

查看视口的尺寸

window.innerWidth/innerHeight (加上 滚动条宽度 / 高度)
IE8及IE8以下不兼容
document.documentElement.clientWidth/clientHeight
标准模式下,任意浏览器都兼容
document.body.clientWidth/clientHeight
适用于怪异模式下的浏览器
封装兼容性方法,返回浏览器视口尺寸getViewportOffset()

脚本化css

特殊的:eg:float — > cssFloat

复合属性必须拆解

查询计算样式

window.getComputesStyle(elem, null);
var style = window.getComputedStyle(div, null);
		//第二个参数是null
		// 选择伪元素
		// null可以获取伪元素

选择after的伪元素

改变伪元素

var after = window.getComputedStyle(div, 'after');

定位的left和top默认值为auto

事件:

事件触发的过程和函数

如何绑定事件处理函数

  1. ele.onxxx = function (event) {} 兼容性很好,但是一个元素只能绑定一个处理程序,属性赋值会被覆盖 基本等同于写在HTML行间上,
  2. ele.addEventListener(type事件类型, fn处理函数, false); IE9以下不兼容,可以为一个事件绑定多个处理程序
  3. ele.attachEvent(‘on’ + type, fn); IE独有,一个事件同样可以绑定多个处理程序

一但事件出现了循环,就要考虑是否出现闭包,就要使用立即执行函数

事件处理程序的运行环境问题

  1. ele.onxxx = function (event) {} 程序this指向是dom元素本身
  2. obj.addEventListener(type, fn, false); 程序this指向是dom元素本身
  3. obj.attachEvent(‘on’ + type, fn); 程序this指向window 封装兼容性的 addEvent(elem, type, handle);方法

解除事件处理程序

ele.onclick = false/‘’/null;
ele.removeEventListener(type, fn, false);
ele.detachEvent(‘on’ + type, fn);

注:若绑定匿名函数,则无法解除

事件冒泡:

结构上(非视觉上)嵌套关系的元素,会存在事件冒泡的功能,急同一个事件,自子元素冒泡向父元素(自底向上)

事件捕获:

结构上(非视觉上)嵌套关系的元素,会存在事件捕获的功能,急同一个事件,自子元素捕获至子元素(自底向下)

如果同时存在冒泡和捕获的时候: 触发顺序,先捕获,后冒泡

focus(聚焦事件),blur,change,submit,reset,select等事件不冒泡

取消冒泡:

W3C标准 event.stopPropagation();但不支持ie9以下版本
IE独有 event.cancelBubble = true;
封装取消冒泡的函数 stopBubble(event)

阻止默认事件:

默认事件 — 表单提交,a标签跳转,右键菜单等
1.return false;  以对象属性的方式注册的事件才生效(兼容性很好)
2.event.preventDefault(); W3C标注,IE9以下不兼容
3.event.returnValue = false; 兼容IE
封装阻止默认事件的函数 cancelHandler(event);

事件源对象:

var target = event.target || event.srcElement

作用:不需要循环所有的元素一个个绑定事件,当有新的子元素的时候,不需要重新绑定所有的事件

鼠标事件:click、mousedown、mousemove(鼠标移动事件)、mouseup、contextmenu(右键取消菜单)、mouseover、mouseout、 mouseenter、mouseleave(效果是一样的)html5里面是写的enter和leave

用button来区分鼠标的按键,0/1/2

onclick = onmousedown + onmouseup

顺序:down、up、click

用button判断当前点击的是鼠标左键还是右键

button == 0表示鼠标左键

button == 2表示鼠标右键

dom3标准规定,click只能监听左键,不能监听右键,能监听的只有onmousedown和onmouseup。

js加载时间线:

执行顺序
1、创建Document对象,开始解析web页面。解析HTML元素和他们的文本内容后添加Element对象和Text节点到文档中。这个阶段document.readyState = 'loading'。
2、遇到link外部css,创建线程加载,并继续解析文档。
3、遇到script外部js,并且没有设置async、defer,浏览器加载,并阻塞,等待js加载完成并执行该脚本,然后继续解析文档。
4、遇到script外部js,并且设置有async、defer,浏览器创建线程加载,并继续解析文档。
对于async属性的脚本,脚本加载完成后立即执行。(异步禁止使用document.write())
5、遇到img等,先正常解析dom结构,然后浏览器异步加载src,并继续解析文档。
6、当文档解析完成,document.readyState = 'interactive'。
7、文档解析完成后,所有设置有defer的脚本会按照顺序执行。(注意与async的不同,但同样禁止使用document.write(),有消除文档流的功能);
8、document对象触发DOMContentLoaded事件,这也标志着程序执行从同步脚本执行阶段,转化为事件驱动阶段。
9、当所有async的脚本加载完成并执行后、img等加载完成后,document.readyState = 'complete',window对象触发load事件。
10、从此,以异步响应方式处理用户输入、网络事件等。

js正则表达式

RegExp

转义字符 \
正常情况下:一个回车代表 \r\n
正则表达式作用:匹配特殊字符或有特殊搭配原则的字符的最佳选择。
正则表达式创建方法:
正则表达式的三个修饰符:
I 忽视大小写
g 全局匹配
m 多行匹配(.
正则表达式的方法:test和字符串上面的方法match,字符串.match(正则表达式)

[参考手册] (www.w3school.com.cn/js/jsref_ob…)

正则表达式的exec()方法: reg.exec();