1、js命名规范
命名一个标识符时需要遵循如下的规则:
1、标识符中可以包含字母、数字、_ (下划线)、$
2、标识符不能以数字开头
3、标识符不能是ES中的关键字或保留字
4、标识符一般都采用驼峰命名法。
2、js数据类型
数据类型指的就是字面量的类型。
在js中一共有6种数据类型:
String:字符串
Number:数值
Boolean:布尔值
Null:空值
Undefined:未定义
Object:对象(引用数据类型,其他的都是基本数据类型)
2.1 typeof
可以使用typeof来检查变量的类型。
var a = 1;
console.log(typeof a);
2.2 Number
Number.MAX_VALUE:1.7976931348623157e+308
Number.MIN_VALUE:5e-324 (大于0最小正值)
如果使用Number表示数字超过了最大值,则会返回一个
Infinity:表示正无穷
-Infinity:表示负无穷
2.3 NaN
NaN是一个特殊的数字,表示:Not a Number
使用typeof检查一个NaN也会返回number
2.4 Null和Undefined
- null:这个值专门用来表示一个一个为空的对象
使用typeof检查一个null值时,会返回object。var a = null; console.log(a);//null console.log(typeof a);//object
- undefined:当声明一个变量,但是并不给变量赋值时,它的值就是
undefined
。
使用typeof检查一个undefined时也会返回undefinedvar a; console.log(a);//undefined console.log(typeof a);//undefined
3 类型转换
3.1 强制类型转换-String
-
方式一:调用被转换变量的
toString()
方法。
注意:null和undefined这两个值没有toString()方法。var a = 123; var b = a.toString(); console.log(b);//123 console.log(typeof b);//string
-
方式二:调用
String()
方法。
对于null和undefined,会直接转换为 “null"和"undefined”var a = 123; var b = String(a); console.log(b);//123 console.log(typeof b);//string var a = null; a = String(a); console.log(a);//null console.log(typeof a);//string var a; a = String(a); console.log(a);//undefined console.log(typeof a);//string
3.2 强制类型转换-Number
- 方式一:使用
Numer()
方法。
1、字符串转为数字:
(1)如果是纯数字的字符串,则直接将其转为数字。
(2)如果字符串中有非数字的内容,则转换为NaN。
(3)如果字符串是一个空串或者是一个全空格的字符串,则返回0。
2、布尔转为数字:
(1)true 转为1
(2)false 转为0
3、null转为数字:0
4、undefined转为数字:NaN - 方式二:
parseInt()
、parseFloat()
,专门把一个字符串转为一个整数/浮点数。
var a ="123"
console.log(parseInt(a));//123
var a ="123abc"
console.log(parseInt(a));//123
var a ="a123bc"
console.log(parseInt(a));//NaN
3.3 强制类型转换-Boolean
使用Boolean()
方法。
1、数字转布尔:除了0和NaN,其余的数字转换为boolean都为true。
var a = 123;
console.log(Boolean(a));//true
var a = 0;
console.log(Boolean(a));//false
var a = NaN;
console.log(Boolean(a));//false
2、字符串转布尔:除了空串,其余都是true。
var a = "123";
console.log(Boolean(a));//true
var a = "";
console.log(Boolean(a));//false
3、null和undefined都是false。
var a = null;
console.log(Boolean(a));//false
var a;
console.log(Boolean(a));//false
4 js对象
对象的分类:
1、内建对象:由ES标准中定义的对象,在任何的ES的实现中都可以使用。
比如:Math、String、Number、Boolean、Function、Object
2、宿主对象:由JS的运行环境提供的对象,目前来讲主要指由浏览器提供的对象。
比如:BOM、DOM
3、自定义对象:由开发人员自己创建的对象。
//创建一个对象:方式一:使用Object创建对象
var a = new Object();
//创建一个对象:方式二:使用对象字面量创建对象
var a = {};
//var a = {
// name:"猪八戒",
// age:"18"
//};
//添加属性:两种方式
a.age = 12;
a.name = "name";
//a["name"] = "name";
//访问属性:两种方式:
console.log(a.name);
console.log(a["name"]);//遍历时只能用这种方式访问
for(var n in a){
console.log(a.n);//不能使用这种方式访问
console.log(a[n]);
}
//修改属性
a.name = "lucy";
console.log(a);
//删除属性:delete关键字
delete a.name;
console.log(a);
5 js函数
创建函数的三种方式:函数的返回值和实参可以是任何类型。
//函数创建方式
//方式一:一般不用
var fun1 = new Function("console.log('fun1')");
fun1();
//方式二
function fun2(){
console.log("fun2");
}
fun2();
//方式三
var fun3 = function(a,b){
console.log("fun3");
};
fun3(1,2);
立即执行函数:
//立即执行函数
(function(a,b){
console.log(a+b);
})(12,34);
函数作为对象的属性称为方法。
6 全局作用域
在JS中一共有两种作用域:全局作用域和函数作用域。
全局作用域:
(1)在全局作用域中有一个全局对象window
,代表浏览器的窗口,由浏览器创建,我们可以直接使用。
(2)在全局作用域中,创建的对象都会作为window
对象的属性保存;创建的函数都会作为window
对象的方法保存。
var a = 10;
console.log(a);
console.log(window.a);
function fun1(){
console.log("fun1");
}
fun1();
window.fun1();
变量的声明提前: 使用var
关键字声明的变量,会在所有的代码执行之前被声明(但是不会赋值),但是如果声明变量时不使用var关键字,则变量不会被声明提前。
//变量的声明提前:相当于:
//var a;
//console.log(a)
//a = 23;
console.log(a);//undefined
var a = 23;
函数的声明提前:
使用函数声明形式创建的函数 function 函数名(){}
,它会在所有的代码执行之前就被创建,所有可以在函数声明前来调用函数。
使用函数表达式创建的函数var fun2 = function(){}
,不会被声明提前,所有不能在声明之前调用。
//函数的声明提前:
fun1();//可以调用
function fun1(){
console.log("fun1");
}
fun2();//报错:is not a function
console.log(fun1);//undefined
var fun2 = function(){
console.log("fun2");
}
7 函数作用域
函数作用域:
(1)调用函数时创建函数作用域,函数执行完毕以后,函数作用域销毁。
(2)每调用一次函数就会创建一个新的函数作用域,他们之间是互相独立的。
(3)在函数作用域中可以访问到全局作用域的变量,如果在函数中有与全局中名称相同的变量,可以通过window.变量名
访问全局变量。
8 this
(1)解析器在调用函数时,每次都会向函数内部传递一个隐含的参数,这个隐含的参数就是this,this指向的是一个对象,这个对象称为函数执行的上下文对象。
(2)根据函数的调用方式的不同,this会指向不同的对象。
以函数的形式调用时,this永远都是window。
以方法的形式调用时,this就是调用方法的那个对象。
//函数的this参数
function fun(){
console.log(this);
}
//以函数的形式调用
fun();//输出window
var obj = {
name:"对象方法",
fun1:fun
}
//以方法的形式调用
obj.fun1();//输出obj对象
9 构造函数
(1)构造函数就是一个普通的函数,创建方式和普通函数没有区别,不同的是构造函数习惯上首字母大写。
(2)普通函数直接调用,而构造函数需要使用new关键字来调用。
(3)构造函数的执行流程:
1、立即创建一个新的对象。
2、将新建的对象设置为函数中的this,在构造函数中可以使用this来引用新建的对象。
3、运行执行函数中的代码。
4、将新建的对象作为返回值返回。
(4)使用同一构造函数创建的对象,称为一类对象,也将一个构造函数称为一个类。
//构造函数
function Person(name,age,gender){
this.name = name;
this.age = age;
this.gender = gender;
this.printName = function(){
console.log(this.name);
}
}
var person1 = new Person("红儿","18","男");
person1.printName();//输出:红儿
console.log(person1);//输出Person对象
console.log(person1 instanceof Person);//输出:true
//所有的对象都是Object的后代
console.log(person1 instanceof Object);//输出true
this关键字总结:
(1)当以函数形式调用时,this就是window对象。
(2)当以方法形式调用时,this是调用该方法的对象。
(3)当以构造函数的形式调用时,this就是新创建的对象。
10 原型对象prototype
创建的每一个函数,解析器都会向函数中添加一个属性prototype
,这个属性对应着一个对象,这个对象就是原型对象。
如果函数作为普通函数调用,prototype没有任何作用。
如果函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象,可以通过__proto__
来访问该属性。
原型对象就相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中公有的内容,统一设置到原型对象中。(作用相当于Java中静态变量或方法)
//直接在构造函数中添加方法的问题:每个对象都会创建自己的方法,占用内存
//解决方式一:将方法定义抽取成全局的方法,在构造函数中使用。
//解决方式二:使用原型对象prototype,将类中公共的方法和变量放在里面
function MyClass(name,age){
this.name = name;
this.age = age;
}
//将公共属性和方法放在原型变量中
MyClass.prototype.a = "原型变量";
MyClass.prototype.say = function(){
console.log("公共方法" + this.name);
}
var mc = new MyClass("红儿",17);
//会先找对象中有没有a变量,没有再去原型对象中找
console.log(mc.a);//原型变量
mc.say();//输出:公共方法红儿
var mc1 = new MyClass("蓝儿",20);
mc1.say();//输出:公共方法蓝儿
10.1 in和hasOwnProperty
(1)in
:检查对象是否含有某个属性,如果对象中没有,但是对象的原型中有,也会返回true。
(2)hasOwnProperty
:检查对象自身中是否含有某个属性。hasOwnProperty是原型对象中的原型对象的方法。
(3)当我们使用一个对象的属性或方法时:
会先在自身中寻找,自身如果有,则直接使用。
如果没有则去原型对象中寻找,如果原型对象中有,则使用,
如果没有则去原型的原型中寻找,直到找到Object对象的原型。
Object对象已经没有原型对象了,如果在Object中依然
没有找到,则返回null。
//1、in:检查对象是否含有某个属性,如果对象中没有,但是对象的原型中有,也会返回true
function MyClass(name,age){
this.name = name;
this.age = age;
}
MyClass.prototype.name1 = "原型对象";
var mc = new MyClass("对象",18);
console.log("name1" in mc);//true
//2、hasOwnProperty:检查对象自身中是否含有某个属性
console.log(mc.hasOwnProperty("name1"));//false
//3、检验hasOwnProperty是不是对象的方法
console.log(mc.hasOwnProperty("hasOwnProperty"));//false
console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false
console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true
console.log(mc.__proto__.__proto__.__proto__);//null
//3.1、结果:hasOwnProperty是对象原型中的原型的方法
10.2 toString()方法
//1、toString:toString是Object的方法
function MyClass(name,age){
this.name = name;
this.age = age;
}
var mc = new MyClass("class1",18);
console.log(mc.toString());//[object,object]
console.log(mc.__proto__.hasOwnProperty("toString"));//false
console.log(mc.__proto__.__proto__.hasOwnProperty("toString"));//true,object的方法
//2、在类中写toString方法,toString自己想要的东西,
function MyClass(name, age) {
this.name = name;
this.age = age;
}
MyClass.prototype.toString = function() {
return this.name + ',' + this.age;
}
var mc = new MyClass("class1", 18);
console.log(mc.toString());//class1,18
11 数组
数组操作的方法:JS数组方法
12 call和apply
call()
和apply()
:
(1)这两个方法都是函数对象的方法,需要通过函数对象来调用。
(2)当对函数调用call()和apply()都会调用函数执行
(3)在调用call和apply时,可以将一个对象指定为第一个参数,此时,这个对象将会成为函数执行时的this。
(4)所以如果需要修改函数执行的this时,可以使用函数对象的这两个方法。
function fun(){
console.log(this);
}
var obj1 = {
name:"obj1"
}
var obj2 = {
name:"obj2"
}
fun.call(obj1);//输出object obj1
fun.apply(obj2);//输出object obj2
call()和apply()的区别:
call()
方法可以将实参在第一个对象后一次传递
apply()
方法需要将实参封装到一个数组中统一传递
function fun(a,b){
console.log(this.name);
console.log(a);
console.log(b);
}
var obj1 = {
name:"obj1"
}
var obj2 = {
name:"obj2"
}
fun.call(obj1,2,3);//输出:obj1 2 3
fun.apply(obj2,[2,3]);//输出:obj2 2 3
13 函数的arguments参数
在调用函数时,浏览器每次都会传递两个隐含的参数:this
和arguments
。
arguments
是一个类数组对象,它可以通过索引来操作,也可以获取长度。在调用函数时,我们所传递的实参都会在arguments中保存。即使不定义形参,在调用函数时传递实参,也可以通过arguments来获取参数。
在arguments中有个属性:callee
,这个属性对应一个函数对象,就是当前正在指向的函数对象。
//arguments
var fun = function(){
console.log(arguments.length)
console.log(arguments[0]);
for(var i = 0;i<arguments.length;i++){
console.log(arguments[i]);
}
console.log(arguments.callee);
}
fun(1,2,true,"hello");
14 Date日期对象
15 正则表达式
正则表达式创建方式一:
var reg = new RegExp("正则表达式","匹配模式");
正则表达式创建方式二:
var reg = /正则表达式/匹配模式;
正则表达式的语法:正则表达式
正则表达式的方法:
test()
:使用该方法来检查字符串是否符合正则表达式的规则。
//正则表达式创建方式一:
// 语法: var reg = new RegExp("正则表达式","匹配模式");
// 第二个参数匹配模式可以是:
// i 忽略大小写
// g 全局匹配模式
// m 执行多行匹配
//正则表达式创建方式二:
// 语法:var reg = /正则表达式/匹配模式
//正则表达式的方法:使用该方法来检查字符串是否符合正则表达式的规则
// test("bca");
var reg = new RegExp("a","i");
console.log(reg.test("Abc"));//true
//使用字面量的方式创建正则表达式:
var reg = /a/i;//匹配字符串中包含a,忽略大小写
console.log(reg.test("abc"));
//正则表达式语法
// a|b:a或者b
// [ab]:a或者b
// [^ab]:除a,b以外的其他任意字符
// [a-z]:任意小写字母
var reg = new RegExp("a|b","i");//匹配的字符串中包含a或者b
console.log(reg.test("ac"));
var reg = new RegExp("[^ab]","i");//匹配的字符串中只要有其他的字符就为true
console.log(reg.test("ab...."));//true
var reg = new RegExp("[a-z]","i");//匹配的字符串中包含a-z的小写字母
console.log(reg.test("ajls."));//true
15.1 字符串和正则相关的方法
search
:检索与正则表达式相匹配的值。
match
:找到一个或多个正则表达式的匹配。
replace
:替换与正则表达式匹配的子串。
split
:把字符串分割为字符串数组。
//1、spilt:将字符串分隔成字符串数组,可以接受一个正则表达式
var str = "1a2b3h4k5n6p7";
var reg = new RegExp("[A-z]");
//根据任意字母来分隔字符串
var arr = str.split(reg);//["1","2","3","4","5","6","7"]
// var arr = str.split(/[A-z]/);
console.log(arr);
//2、search:可以搜索字符串中是否包含指定内容,可以接受一个正则表达式
// 如果搜索到,就返回第一次搜索到的索引,否则返回-1
var str = "dls abc aec afc";
var reg = new RegExp("a[a-z]c")
var index = str.search(reg);
console.log(index);//4
//3、match:从一个字符串中将符合条件的内容提取出来(字符串数组),可以接受一个正则表达式
// 默认情况下match只会找到一个符合要求的内容,找到以后就停止检索
// 我们可以设置正则表达式为全局匹配模式,这样就会匹配到所有的内容
var str = "1a2b3h4k5n6p7";
var matchResult1 = str.match(/[a-z]/);
console.log(matchResult1);//["a"]
var matchResult = str.match(/[a-z]/ig);//匹配任意字母,全局忽略大小写
console.log(matchResult);//["a","b","h","k","n","p"]
//3、replace:可以将字符串中指定内容替换为新的内容
// -参数:
// 1、被替换的内容,可以接受一个正则表达式作为参数
// 2、新的内容
// -默认只会替换第一个
var str = "1a2a3a4j5n";
var replaceResult = str.replace("a","@_@");
console.log(replaceResult);//1@_@2a3a4j5n
var replaceResult = str.replace(/a/g,"@_@");
console.log(replaceResult);//1@_@2@_@3@_@4j5n
15.2 正则表达式的语法
方括号
a|b
:a或者b
[ab]
:a或者b
[^ab]
:除a,b以外的其他任意字符
[a-z]
:任意小写字母
[A-z]
:任意字母
[0-9]
:任意数字
量词
量词:通过量词可以设置一个内容出现的次数;量词只对它前边的一个内容起作用。
-{n}
正好出现n次
-{m,n}
出现m-n次
-{m,}
出现m次及以上
-+
至少一个,相当于{1,}
- *
0个或者多个,相当于{0,}
-?
0个或者1个,相当于{0,1}
- ^a
以a开头
- a$
以a结尾
-a?=b
匹配 a 后面为b 的 a
- a?!b
匹配a 后面不为b 的 a
var str = "abbbc";
var reg = /ab{3}c/;
console.log(reg.test(str));
var str = "abbbbc";
var reg = /ab{1,3}c/;
console.log(reg.test(str));
var str = "abc";
var reg = /ab+c/;
console.log(reg.test(str));//true
var str = "ac";
var reg = /ab*c/;
console.log(reg.test(str));//true
var str = "hello world";
var reg = /ll(?=o)/;//匹配 ll后为o 的 ll
console.log(str.match(reg));//["ll"]
var reg = /ll(?!o)/;//匹配 ll后不为o 的 ll
console.log(str.match(reg));//null
//手机号正则表达式:1 3 576982485 (11位)
// 1、以1开头 ^1
// 2、第二位3-9任意数字 [3-9]
// 3、三位以后任意数字9个 [0-9]{9}
// ^1 [3-9] [0-9]{9}$
var phoneNum = "14598279244";
var reg = /^1[3-9][0-9]{9}$/;
console.log(reg.test(phoneNum));
元字符
.
表示任意字符。
在正则表达式中\也具有特殊意义,表示转义
用 \. 来表示 .
用 \\ 来表示 \\w
表示任意字母、数字、_ 相当于[A-z0-9_]\W
除了字母、数字、_ 相当于[^A-z0-9_]\d
任意数字[0-9]\s
空格\S
除了空格\b
单词边界\B
除了单词边界
/**正则语法:元字符
* - . 表示任意字符。
* 在正则表达式中\也具有特殊意义,表示转义
* 用 \. 来表示 .
* 用 \\ 来表示 \
* - \w 表示任意字母、数字、_ 相当于[A-z0-9_]
* - \W 除了字母、数字、_ 相当于[^A-z0-9_]
* - \d 任意数字[0-9]
* - \s 空格
* - \S 除了空格
* - \b 单词边界
* - \B 除了单词边界
*/
/**
* 注意:使用构造函数时,由于它的参数是一个字符串,而\是字符串中的转义字符,
* 如果要使用\则需要使用\\来替代
*/
//1、检查字符串中是否含有 .
var reg = /./;//.在正则中含有特殊意义,所以不能直接用它来检查字符串中是否含有.,需转义
console.log(reg.test("adv"));//true
var reg = /\./;
console.log(reg.test("."));//true
console.log(reg.test("abc"));//false
var reg = /\\/;//检查字符串中是否含有\
console.log(reg.test("jd\\"));
//使用构造函数来创建
var reg = new RegExp("\\\\","g");// = reg = /\\/
console.log(reg.test("\\"));//true
var reg = /a*/;
var str = "fdddaaaddaad";
console.log(str.match(reg));
//单词边界:child
var reg = /child/;
console.log(reg.test("children"));//true
var reg = /\Bchild\B/;
console.log(reg.test("children"));//false
console.log(reg.test("hello,child!"));//true
//去掉字符串开头和结尾的空格
var reg = /\s/;//匹配开头的一个空格
var reg = /\s*/;//匹配开头的多个空格
var reg = /\s*$/;//匹配结尾的多个空格
var reg = /^\s*|\s*$/;//匹配开头或者结尾的空格
var reg = /^\s*|\s*$/g;//匹配开头和结尾的空格(全局匹配)
// var reg = /^\s+|\s+$/g;//写成+号:匹配一个或者多个空格
var str = "hel lo";
console.log(str.replace(reg,"6"));
DOM
DOM(document Object Model)文档对象模型。JS通过DOM可以操作html文档。
文档:文档表示的就是整个HTML网页文档。
对象:对象表示将网页中的每一个部分转换为了一个对象。
模型:使用模型来表示对象之间的关系,这样方便我们获取对象。体现文档中节点与节点之间的关系。
节点:Node—构成HTML文档最基本的单位。常用节点分为四类:文档节点、元素节点、属性节点、文本节点。
事件冒泡
事件委派
事件绑定
方式1:btn.onclick = function(){};
方式2:btn.addEventListener(‘click’,function(){},false);
addEventListener(事件字符串-不需要on,回调函数,是否在捕获节点触发事件-一般都是false)
如果一个事件由window调用,事件中的this为window,要想改变自定义事件中this,可以再事件外包一个匿名函数,在匿名函数中调用自定义事件(call),修改事件的this
事件传播
关于事件的传播网景公司和微软公司有不同的理解
- 微软公司认为事件应该是由内往外传播,也就是当事件触发时,应该先触发当前元素上的事件,然后再向当前元素的祖先元素上传播,也就是说事件应该在冒泡阶段执行。
- 网景公司认为事件应该是有外向内传播的,也就是当事件触发时,应该先触发当前元素的最外层的祖先元素的事件,然后再向内传播给后代元素。
W3C综合了两个公司的方案,将事件的传播分成了三个阶段:
1、捕获阶段(IE9及以上)
在捕获阶段时从最外层的祖先元素,像目标元素事件的捕获,但是默认此时不会触发事件。
2、目标阶段
事件捕获到目标元素,捕获结束开始在目标元素上触发事件
3、冒泡阶段
事件从目标元素向他的祖先元素传递,依次触发祖先元素上的事件。
如果希望在捕获阶段就执行事件,btn.addEventListener(‘click’,function(){},true
);