一、JS引入
- 内嵌引入,不建议使用
<button id="button" οnclick="javascript:alert('js引入的方式3:事件定义')">实验</button>
- 在</body>前通过<script></script>标签引入
- 在<head>部分用<script></script>引入
type="text/JavaScript"可以省略
Sync:同步
Async:异步
async='async'和defer='defer'都是异步下载,区别在:
async='async'是立即异步下载外部JS,不影响页面其它的操作,js下载完毕立即执行;
defer='defer'是在js,css整个文档都下载完后再执行,只有外部脚本可以使用
二、数据类型
基本数据类型:string、number、boolean、null、undefined
ES6新添:symbol (它的值是唯一的,不可变的)
复杂数据类型:Object
引用类型:引用类型值指那些可能由多个值构成的对象,基本类型值是按值访问的,可以操纵保存在变量中的实际的值,而引用类型值是保存在内存中的对象,实际上是操作对象的引用。
判断数据的类型:typeof(变量/直接量) 可省略括号:typeof变量/直接量
JS不支持自己创建数据类型。鉴于数据类型是松散型的,我们用typeof来请确定变量的类型。其中NULL会返回OBJECT,可以把NULL理解成一个指向空对象的指针,因此NULL是有意义的,而UNDEFINED没有什么意义,从来不会故意给一个变量声明为UNDEFINED。TYPEOF除了上述几种数据类型,还能检测出FUNCTION,虽然FUNCTION本质上来说也是一种对象。
1、string方法
str.charAt(下标):查找下标对应的字符串;
str.indexOf('字符串'):从左往右查找字符串所对应的下标;找不到时返回-1;
str.lastIndexOf('字符串') 从右往左查找字符串所对应的下标;
str.split('切割方法'):将字符串以括号中的方式切割成数组;
str.substring(开始的位置,结束的位置):截取从开始到结束位置的字符串;
str.toUpperCase(); 字符串中的字母全部转换成大写;
str.toLowerCase(); 字符串中的字母全部转换成小写;
2、number相关方法
Math.random()随机数
Math.abs() 绝对值
Math.sqrt() 开方
Math.pow(n,m) n的m次方
Math.ceil() 向上取整
Math.floor() 向下取整
Math.round() 四舍五入
Math.max() 最大值
Math.min() 最小值
3、数组方法
arr.push() 向后添加一项;
arr.unshift() 向前添加一项;
arr.pop() 从后边删除一项;
arr.shift() 从前边删除一项;
arr.splice(开始的位置,删除的个数,添加项);
arr.reverse() 翻转;
arr.join('拼接方式') 将数组中的每一项拼接成一个字符串;
arr.sort(function(n,m){return n-m}); 排序 里面参数和返回值顺序相同时是从小到达,反之是从大到小
arr.concat(arr1,arr2) 数组的拼接;
Object类型有以下属性和方法:
constructor:保存着用于创建当前对象的函数,new Object() 构造函数函数就是Object()
hasOwnProperty()用于检查给定的属性在当前对象实例中是否存在(注意不是在实例的原型中检测 )
isPrototypeOf()用于检查传入的对象是否是当前对象的原型
propertyIsEnumerable()用于检查当前属性能否用FOR-IN枚举
还有toString toLocaleString valueOf三个方法
三、数据类型的转换
强制转换
1、数值转字符串:
法一:直接调用.toString方法可以将内容直接转成字符串
法二:直接将要转的内容放在string后的括号中
区别:一是直接调用这个变量对象的方法, 第二个是强制转换
2、Boolean转string
使用函数Boolean();
注意:除了false、空字符串“”、0、NaN、undefined在转换是灰转成false,其余都会转成true
3、转number
number();(如果是小数,小数会保留)
parseInt();
parseFloat();
隐式转换(浏览器自行转换)
1、隐式转换成Number:直接在要转换的内容前加上+-*\%/
2、隐式转换成string:直接在要转换的内容后加“”
3、隐式转换成Boolean:直接将a = !!a;或者!a
四、运算符的优先级
下表按从最高到最低的优先级列出JavaScript运算符。具有相同优先级的运算符按从左至右的顺序求值
运算符 | 描述++ |
++ -- - + ~ ! delete new typeof void | 一元运算符、返回数据类型、对象创建、未定义值 |
* / % | 乘法、除法、取模 |
+ - + | 加法、减法、字符串连接 |
<< >> >>> | 位移 |
< <= > >= instanceof | 小于、小于等于、大于、大于等于、instanceof |
== != === !== | 等于、不等于、严格相等、非严格相等 |
&& | 逻辑与 |
|| | 逻辑或 |
? : | 三元操作 |
= | 赋值、运算赋值 |
五、函数
函数定义:
1、函数声明
注意:函数名称和函数体会提升置顶,函数声明语句创建的变量无法删除
function funcname([arg1 [,arg2 [...,argn]]]){
statement;
}
2、函数定义表达式
var functionName = function([arg1 [,arg2 [...,argn]]]){
statement;
}
3、Function构造函数
Function构造函数接收任意数量的参数,但最后一个参数始终都被看成是函数体,而前面的参数则枚举出了新函数的参数
var functionName = new Function(['arg1' [,'arg2' [...,'argn']]],'statement;');
[注意]Function构造函数无法指定函数名称,它创建的是一个匿名函数
从技术上讲,这是一个函数表达式。但,不推荐使用,因为这种语法会导致解析两次代码。第一次是解析常规javascript代码,第二次解析传入构造函数中的字符串,影响性能
var sum = new Function('num1','num2','return num1 + num2');
//等价于
var sum = function(num1,num2){
return num1+num2;
}
Function()构造函数创建的函数,其函数体的编译总是会在全局作用域中执行。于是,Function()构造函数类似于在全局作用域中执行的eval()
var test = 0;
function fn(){
var test = 1;
return new Function('return test');
}
console.log(fn()());//0
[注意]并不是所有的函数都可以成为构造函数
var o = new Math.min();//Uncaught TypeError: Math.min is not a constructor
函数调用
只有函数被调用时,才会执行。调用运算符是跟在任何产生一个函数值的表达式之后的一对圆括号,圆括号内可包含零个或多个用逗号隔开的表达式。每个表达式产生一个参数值,每个参数值被赋予函数声明时定义的形参名
javascript一共有4种调用模式:函数调用模式、方法调用模式、构造器调用模式和间接调用模式
1、函数调用模式
当一个函数并非一个对象的属性时,那么它就是被当做一个函数来调用的。对于普通的函数调用来说,函数的返回值就是调用表达式的值
function add(x,y){
return x+y;
}
var sum = add(1,2);
console.log(sum)//3
使用函数调用模式调用函数时,非严格模式下,this被绑定到全局对象;在严格模式下,this是undefined
function a(){
console.log(this);//window
}
a();
function b(){
'use strict';
console.log(this);//undefined
}
b();//window
因此,'this'可以用来判断当前是否是严格模式
var strict = (function(){return !this;}());
重写现象
因为函数调用模式的函数中的this绑定到全局对象,所以会发生全局属性被重写的现象
var a = 0;
function fn(){
this.a = 1;
}
fn();
console.log(this,this.a,a);//window 1 1
2、方法调用模式
当一个函数被保存为对象的一个属性时,我们称它为一个方法。当一个方法被调用时,this被绑定到该对象。如果调用表达式包含一个提取属性的动作,那么它就是被当做一个方法来调用
var o = {
m: function(){
console.log(1);
}
};
o.m();//1
方法可以使用this访问自己所属的对象,所以它能从对象中取值或对对象进行修改。this到对象的绑定发生在调用的时候。通过this可取得它们所属对象的上下文的方法称为公共方法
var o = {
a: 1,
m: function(){
return this;
},
n: function(){
this.a = 2;
}
};
console.log(o.m().a);//1
o.n();
console.log(o.m().a);//2
任何函数只要作为方法调用实际上都会传入一个隐式的实参——这个实参是一个对象,方法调用的母体就是这个对象,通常来讲,基于那个对象的方法可以执行多种操作,方法调用的语法已经很清晰地表明了函数将基于一个对象进行操作
和变量不同,关键字this没有作用域的限制,嵌套的函数不会从调用它的函数中继承this。如果嵌套函数作为方法调用,其this的值指向调用它的对象。如果嵌套函数作为函数调用,其this值不是全局对象(非严格模式下)就是undefined(严格模式下)
var o = {
m: function(){
function n(){
return this;
}
return n();
}
}
console.log(o.m());//window
var o = {
m: function(){
function n(){
'use strict';
return this;
}
return n();
}
}
console.log(o.m());//undefined
var o = {
m: function(){
var self = this;
console.log(this === o);//true
function n(){
console.log(this === o);//false
console.log(self === o);//true
return self;
}
return n();
}
}
console.log(o.m() === o);//true
如果想访问这个外部函数的this值,需要将this的值保存在一个变量里,这个变量和内部函数都同在一个作用域内。通常使用变量self或that来保存this
3、构造函数调用模式
如果函数或者方法调用之前带有关键字new,它就构成构造函数调用
function fn(){
this.a = 1;
};
var obj = new fn();
console.log(obj.a);//1
如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内
function fn(x){
this.a = x;
};
var obj = new fn(2);
console.log(obj.a);//2
如果构造函数没有形参,javascript构造函数调用的语法是允许省略实参列表和圆括号的。凡是没有形参的构造函数调用都可以省略圆括号
var o = new Object();
//等价于
var o = new Object;
[注意]尽管构造函数看起来像一个方法调用,它依然会使用这个新对象作为调用上下文。也就是说,在表达式new o.m()中,调用上下文并不是o
var o = {
m: function(){
return this;
}
}
var obj = new o.m();
console.log(obj,obj === o);//{} false
console.log(obj.constructor === o.m);//true
构造函数通常不使用return关键字,它们通常初始化新对象,当构造函数的函数体执行完毕时,它会显式返回。在这种情况下,构造函数调用表达式的计算结果就是这个新对象的值
function fn(){
this.a = 2;
}
var test = new fn();
console.log(test);//{a:2}
如果构造函数使用return语句但没有指定返回值,或者返回一个原始值,那么这时将忽略返回值,同时使用这个新对象作为调用结果
function fn(){
this.a = 2;
return;
}
var test = new fn();
console.log(test);//{a:2}
如果构造函数显式地使用return语句返回一个对象,那么调用表达式的值就是这个对象
var obj = {a:1};
function fn(){
this.a = 2;
return obj;
}
var test = new fn();
console.log(test);//{a:1}
4、简介调用模式
javascript中函数也是对象,函数对象也可以包含方法。call()和apply()方法可以用来间接地调用函数
这两个方法都允许显式指定调用所需的this值,也就是说,任何函数可以作为任何对象的方法来调用,哪怕这个函数不是那个对象的方法。两个方法都可以指定调用的实参。call()方法使用它自有的实参列表作为函数的实参,apply()方法则要求以数组的形式传入参数
var obj = {};
function sum(x,y){
return x+y;
}
console.log(sum.call(obj,1,2));//3
console.log(sum.apply(obj,[1,2]));//3
六、获取元素
1、通过id
var oBtn=document.getElementById('btn1');
2、通过标签
var aDiv=document.getElementsByTagName('div');
操作一组元素就要用循环:
for(初始值;循环条件;自增自减条件){} 有长度的用for循环
初始值;while(循环条件){代码;自增自减条件;} 没有长度的用while循环;
for in循环:对象中使用:json arr arr中一般用上边的for循环性能高;
3、通过class
var aDiv=document.getElementsByClassName('div1');
有兼容性问题:通过封装函数来解决:
getByClass(oBox,'div1');
function getByClass(obj,sName){
var aObj=obj.getElementsByTagName('*');
var arr2=[];
for(var i=0;i<aObj.length;i++){
var str=aObj[i].className;
var arr=str.split(' ');
if(findInArr(sName,arr)){
arr2.push(aObj[i]);
};
}
return arr2;
}
[
注意]获取出来的一组与元素是类数组 可意识使用长度aDiv.length 和 下标aDiv[0] 不能使用数组的其他方法;
七、事件
系统事件:onload\DOMContentLoaded\onreadystatechange\onscroll\onresize
鼠标事件:onclick\onmouseover\onmouseout\onmousedown\onmouseup\onmousemove\onmousewheel\DOMMouseScroll\ oncontextmenu\
键盘事件:onkeydown\onkeyup\oninput\onpropertychange\
事件对象:存储事件发生的详细信息;声明 var oEvent=ev||event;
DOM事件必须绑定;且DOM事件只能在高级浏览器中兼容;
obj.attachEvent('带on的事件名',fn);兼容IE浏览器;
事件冒泡:从下往上一级一级传递的事件流,一般不阻止冒泡,有问题才阻止;
oEvent.cancelBubble=true;
事件下沉:与事件冒泡相反的事件流,从上往下一级一级传递;
常见的对象信息
oEvent.target||oEvent.srcElement;
oEvent.clientX;/oEvent.clientY;
oEvent.keyCode/oEvent.shiftKey/oEvent.altKey/oEvent.ctrlKey;
oEvent.wheelDelta/oEvent.detail
参考文档
【1】梳理一下JS的基本用法:点击打开链接
【2】深入理解JavaScript函数系列第一篇:点击打开链接
【3】js知识体系的梳理一:点击打开链接
【4】JS基础知识点梳理: 点击打开链接