JS基础操作

javascript介绍

JavaScript操作DOM的本质是=获取+触发+改变
目的:就是用来操作内存中的DOM节点

变量

变量本质是一个空盒子,里面记录了一个内存地址,使能找到内存中的对象,保存了指向具体的实在的东西的地址
变量存在栈中,对象存在堆中
变量的意义:方便我们去操作对象

window作用域

只要在script标签中定义的变量,默认就在window的作用域之下
默认就是window这个对象里面写代码

数据类型

如何判断js中的数据类型:
typeof、instanceof、 constructor、 prototype方法比较

如何判断js中的类型呢,先举几个例子:

1
2
3
4
5
6
var a = "iamstring.";
var b = 222;
var c= [1,2,3];
var d = new Date();
var e = function(){alert(111);};
var f = function(){this.name="22";};

最常见的判断方法:typeof

1
2
3
4
5
6
alert(typeof a) ------------> string
alert(typeof b) ------------> number
alert(typeof c) ------------> object
alert(typeof d) ------------> object
alert(typeof e) ------------> function
alert(typeof f) ------------> function

其中typeof返回的类型都是字符串形式,需注意,例如:

1
2
alert(typeof a == "string") -------------> true
alert(typeof a == String) ---------------> false

另外typeof可以判断function的类型;在判断除Object类型的对象时比较方便。
判断已知对象类型的方法:instanceof

1
2
3
4
alert(c instanceof Array) ---------------> true
alert(d instanceof Date)---------------> true
alert(f instanceof Function) ------------> true
alert(f instanceof function) ------------> false

注意:instanceof后面一定要是对象类型,并且大小写不能错,该方法适合一些条件选择或分支。
根据对象的constructor判断:constructor

1
2
3
alert(c.constructor === Array) ----------> true
alert(d.constructor === Date) -----------> true
alert(e.constructor === Function) -------> true

注意: constructor 在类继承时会出错

例子:

1
2
3
4
5
6
function A(){};
function B(){};
A.prototype = new B(); //A继承自B
var aObj = new A();
alert(aobj.constructor === B) -----------> true;
alert(aobj.constructor === A) -----------> false;

而instanceof方法不会出现该问题,对象直接继承和间接继承的都会报true:

1
2
alert(aobj instanceof B) ----------------> true;
alert(aobj instanceof B) ----------------> true;

言归正传,解决construtor的问题通常是让对象的constructor手动指向自己:

1
2
3
aobj.constructor = A; //将自己的类赋值给对象的constructor属性
alert(aobj.constructor === A) -----------> true;
alert(aobj.constructor === B) -----------> false; //基类不会报true了;

通用但很繁琐的方法: prototype

1
2
3
4
5
6
alert(Object.prototype.toString.call(a) === ‘[object String]’) -------> true;
alert(Object.prototype.toString.call(b) === ‘[object Number]’) -------> true;
alert(Object.prototype.toString.call(c) === ‘[object Array]’) -------> true;
alert(Object.prototype.toString.call(d) === ‘[object Date]’) -------> true;
alert(Object.prototype.toString.call(e) === ‘[object Function]’) -------> true;
alert(Object.prototype.toString.call(f) === ‘[object Function]’) -------> true;

大小写不能写错,比较麻烦,但胜在通用。
通常情况下用typeof判断就可以了,遇到预知Object类型的情况可以选用instanceof或constructor方法

Javascript数据类型

Javascript的数据类型有六种(ES6新增了第七种Symbol)

数值(number):整数和小数(比如1和3.14)
字符串(string):字符组成的文本(比如”Hello World”)
布尔值(boolean):true(真)和false(假)两个特定值
undefined:表示 未定义 或不存在,即此处目前没有任何值
null:表示空缺,即此处应该有一个值,但目前为空
对象(object):各种值组成的集合
通常,我们将数值、字符串、布尔值称为原始类型(primitive type)的值,即它们是最基本的数据类型,不能再细分了。而将对象称为合成类型(complex type)的值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值

内存中一共分为几种对象:变量、DOM对象、常量、自定义对象

数据类型转换

转换函数

toString() 转换为字符串,在JavaScript中所有数据类型都可以转换为string类型,toString() 括号中的可以写一个数字,代表进制,对应进制字符串

1
2
3
4
5
6
7
8
9
10
11
var n1 = 12;
var n2 = true;
var a = [1, 2, 3];
var o = {};
function f(){}
n1.toString(); //"12"
n2.toString(); //"true"
a.toString(); //"1,2,3"
o.toString(); //"[object Object]"
f.toString(); //"function f(){}"

parseInt()解析出一个string或者number类型的整数部分,如果没有可以转换的部分,则返回NaN(not a number)

1
2
3
4
5
6
7
var n1 = "12";
var n2 = "23hello";
var n3 = "hello";
parseInt(n1); //12
parseInt(n2); //23
parseInt(n3); //NaN

parseFloat()解析出一个string的浮点数部分,如果没有可以转换的部分,则返回NaN(not a number)

1
2
3
4
5
6
7
var n1 = "1.2.3";
var n2 = "1.2hello"
var n3 = "hello"
parseFloat(n1); //1.2
parseFloat(n2); //1.2
parseFloat(n3); //NaN

强制类型转换
Boolean(value)- 把给定的值转换成Boolean型

1
2
3
4
5
6
Boolean(123); //true
Boolean(""); //false
Boolean([]); //true
Boolean({}); //true
Boolean(null); //false
Boolean(undefined); //false

Number(value)-把给定的值转换成数字(可以是整数或浮点数)

1
2
3
4
5
6
7
8
Number("123"); //123
Number("123h"); //NaN
Number(true); //1
Number(false); //0
Number(undefined); //NaN
Number(null); //0
Number([]); //0
Number({}); //NaN

String(value)- 把给定的值转换成字符串

1
2
3
4
5
String(123); //"123"
String([1,2]); //"1,2"
String(undefined) //"undefined"
String(null) //"null"
String({}) //"[object Object]"

隐式转换
数字+字符串:数字转换为字符串 console.log(12+"12"); //1212
数字+布尔值:true转换为1,false转换为0 console.log(12+true); //13
字符串+布尔值:布尔值转换为true或false console.log("hello"+true); //hellotrue
布尔值+布尔值 console.log(true+true); //2
null和undefined
undefined 表示一种未知状态,声明了但没有初始化的变量,变量的值是一个未知状态。访问不存在的属性或对象方法没有明确返回值时,返回值是一个undefined.当对未声明的变量应用typeof运算符时,显示为undefined。
null表示尚未存在的对象,null是一个有特殊意义的值。可以为变量赋值为null,此时变量的值为“已知状态”(不是undefined),即null。(用来初始化变量,清除变量内容,释放内存)
undefined==null //结果为true,但含义不同。
undefined===null //false,两者类型不一致,前者为“undefined”,后者为“object”

javascript脚本执行顺序

第一步定义: 分为var定义 和函数定义function
第二步执行: 其他所有
先从上往下定义完所有的后,再从上往下执行 除了var function定义外的 其他都是执行 如:赋值 函数调用
在栈里面找到的,就不去堆里面找,因为栈空间小,就近原则【总之:先在栈里面找,找不到再去堆里面找】在栈里面开辟,就能找到堆里面的地址 如:var b = function(){}

总结一下==运算的规则:(隐式转换)
JS中的值有两种类型:原始类型(Primitive)、对象类型(Object)。
原始类型包括:Undefined、Null、Boolean、Number和String等五种。
Undefined类型和Null类型的都只有一个值,即undefined和null;Boolean类型有两个值:true和false;Number类型的值有很多很多;String类型的值理论上有无数个。
所有对象都有valueOf()toString()方法,它们继承自Object,当然也可能被子类重写

undefined == null,结果是true。且它俩与所有其他值比较的结果都是false。
String == Boolean,需要两个操作数同时转为Number。
String/Boolean == Number,需要String/Boolean转为Number。

Object == Primitive,需要Object转为Primitive(具体通过valueOf和toString方法)

运算符

算术运算符(+,-,*,/,%,++,--)

如果引用所指的地方是null的话,那么在运算中就会自动变成0
%运算符 如:4%5取模 模是4 7%5取模 模是7-5=2

字符串和数字相加的情况:

左右都是数字:数字相加
左右有一个字符串:字符串拼接
左右边有一个null:null看做0
左右边有一个undefined:结果是NAN(not is number)

赋值运算符(=,-=,+=,*=,/=,%=)

比较运算符(==,===,!=,>,<,>=,<=)

先执行表达式计算再赋值
==!=在比较之前首先让双方的值做隐士类型转换,===不转换

逻辑运算符(||,&&,!)

|| 短路运算 第一个条件为真 后面不执行,当有一个true时,返回true一侧的值;当有两个true时,返回运算符之前(左侧)的值;当有两个false时,返回运算符之后(右侧)的值。
&&逻辑与返回其运算符左右两旁的一个值,当有一个false时,返回false一侧的值;当有两个false时,返回运算符之前(左侧)的值;当有两个true时,返回运算符之后(右侧)的值。

条件运符(表达式1?表达式2:表达式3)三元运算符

表达式1?表达式2:表达式3 表达式1为真 返回表达式2 否则返回表达式3
三元运算符 可以多层次嵌套使用

在js中 有四种被认为是非:undefined、null、false、0
例子:var age = prompt("温馨提示:","请输入您的年龄")||0
当点击取消的时候,如果出现undefined null fasle 0 表示非的逻辑 那么||就会过滤,取右边的值0

console.log调试程序

开发中大量使用这个 而不用alert

条件结构

if
javascript中if语句优化写法
使用常见的三元操作符

1
2
3
if (foo) bar(); else baz(); ==> foo?bar():baz();
if (!foo) bar(); else baz(); ==> foo?baz():bar();
if (foo) return bar(); else return baz(); ==> return foo?bar():baz();

使用and(&&)和or(||)运算符

1
2
if (foo) bar(); ==> foo&&bar();
if (!foo) bar(); ==> foo||bar();

if…else
if…else if…else
当通过判断返回某个值的时候,优先使用三元表达式
当通过判断执行N段逻辑代码的时候,只能用条件结构

switch
switch case break default 条件 判断 退出 默认
a. 只要匹配上一个case,那么它下面的所有的case都会执行包括default
b. break的意思跳出当前结构

for
循环有三个要素
a. 循环变量
b. 判断(循环体)
c. 改变循环变量

continue 结束本次循环,继续下一次循环 当前这次循环不做 直接做下面的
break 结束后面的循环不做了

while/do…while 没有谁好谁坏 只有适应场景不同
比如:先吃饭 再买单 do..while 用户体验高 有风险 扫雷游戏也是先体验 再问是否退出 提高体验
比如:先买单 再吃饭 while 用户体验不高
一般情况下面,如果条件判断是数字的比较==<>,for循环优先.
如果是非数值相关的比较循环,while优先

代码内存解析

闭包
a. 程序永远是先定义后执行
b. 执行永远从上到下
c. 函数定义的话在堆(只是一个地址而已)
d. 函数调用的时候,就会有自己的堆和栈(闭包)

定义在堆中的函数本身是一个小的封闭空间,也有栈和堆

object对象

new关键字代表的是新开辟一块内存空间
没有被引用的内存空间,会在适当的时候被销毁

两句代码含义等同

1
2
var person = new Object();
var person = {};

访问对象的属性除了用 对象引用.属性 key以外,还可以使用对象引用[属性key]

new 原理详细解析

无论什么时候,只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。

在默认情况下,所有原型对象都会自动获得一个constructor(构造函数)属性,这个属性包含一个指向prototype属性所在函数的指针(就是指向新创建的函数)。
通过这个构造函数(原型对象的构造函数),可以继续为原型对象添加其他属性和方法。

当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。ECMA-262第5版管这个指针叫 [[Prototype]]。脚本中没有标准的方式访问[[Prototype]],但Firefox、Safari和Chrome在每个对象上都支持一个属性proto;而在其他实现中,这个属性对脚本是完全不可见的。不过,要明确的真正重要的一点就是,这个连接存在于实例和构造函数的原型对象之间,而不是存在于实例和构造函数之间
new创建对象的步骤
1 创建一个新的对象
2 将构造函数的作用域赋给新对象
3 执行构造函数的代码,为这个新对象添加属性
4 返回新对象

面向对象的程序设计

function构造器
共同点:
动态创建一块内存空间,闭包
不同点:
函数调用是没有办法拿到空间的地址的,而且这块地址是一块临时地址,执行完函数之后,就会销毁
new开辟内存空间,把这块空间的地址返回,这块空间就有可能长期的被引用

prototype内存解析
prototype是原型,是一块所有对应构造器创建的对象都共享的内存空间
在面向对象设计程序的时候,属性应该是对应的空间的,而功能应该是prototype公共空间的

通过prototype扩展功能
所有的构造器都是继承于Object构造器的,因此只要Object的原型里有的功能,所有的对象都有

继承
本质就是从一个prototype对象中把它的功能都copy到另一个prototype对象

call apply bind方法的使用

这三个方法都是改变this的指向
call和apply
没参数一样
有参数call一次传入 call(elemet,foo1,foo2,foo3)
有参数apply传入一个数组参数 apply(element,[foo1,foo2,foo3]);

call和bind
有参数传入一样
但是bind后边要加()执行
使用bind其实创建了一个函数 调用就需要在加()执行

func.call(obj):调用func的时候,以obj这个对象的作用域去调用

改变函数在调用的时候里面闭包的作用域

call和apply总结
call(obj,arg1,arg2,arg3);call第一个参数传对象,可以是null。参数以逗号分开进行传值,参数可以是任何类型。
apply(obj,[arg1,arg2,arg3]);apply第一个参数传对象,参数可以是数组或者arguments对象

常用API

日期型函数Date
声明

1
2
3
4
5
6
var myDate = new Date(); //系统当前时间
var myDate = new Date(yyyy, mm, dd, hh, mm, ss);
var myDate = new Date(yyyy, mm, dd);
var myDate = new Date(“monthName dd, yyyy hh:mm:ss”);
var myDate = new Date(“monthName dd, yyyy”);
var myDate = new Date(epochMilliseconds);

获取时间的某部份

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var myDate = new Date();
myDate.getYear(); //获取当前年份(2位)
myDate.getFullYear(); //获取完整的年份(4位,1970-????)
myDate.getMonth(); //获取当前月份(0-11,0代表1月)
myDate.getDate(); //获取当前日(1-31)
myDate.getDay(); //获取当前星期X(0-6,0代表星期天)
myDate.getTime(); //获取当前时间(从1970.1.1开始的毫秒数) 时间戳!!
myDate.getHours(); //获取当前小时数(0-23)
myDate.getMinutes(); //获取当前分钟数(0-59)
myDate.getSeconds(); //获取当前秒数(0-59)
myDate.getMilliseconds(); //获取当前毫秒数(0-999)
myDate.toLocaleDateString(); //获取当前日期
myDate.toLocaleTimeString(); //获取当前时间
myDate.toLocaleString( ); //获取日期与时间

BOM 浏览器对象模型

BOM

a. screen 指的不是浏览器的宽度,指的是整个电脑屏幕的分辨率
可以拿到屏幕可用分辨率

b. navigator
可以通过userAgent判断当前浏览器信息

c. location
URL:统一资源定位符 Union Resource Location
可以通过href属性重定向(改变)页面的URL,进行页面跳转

d.history
go方法能够让我们进行历史回退或者前进

e.frames
获得当前窗体的子页面(iframe)

f.document
DOM模型的核心对象

DOM 文档对象模型

document
功能
getElementById:通过传入的ID,返回标识了这个ID的唯一对象的内存地址
getElementsByTagName: 通过传入的标签名字,返回所有该标签对象(HTMLCollection)
getElementsByClassName: 通过类的名字,返回所有该类的元素对象(HTMLCollection)
createElement: 想要创建出来的元素能够绘制在页面中,那么它必须在DOM树中
总结 document对象是DOM原型的核心对象,它是内存DOM树的根,所以它提供了很多功能让我们快速的找到DOM树中的某些DOM节点(对象)

element
功能方法:(自定义属性非常灵活好用)
getAttribute获取标签的属性 –用来操作标签的属性
setAttribute设置标签的属性
appendChild:添加子元素

属性:
id
className,style
name,value(只有表单元素有 其他是没有的)
href,src…(对应的元素)
innerHTML/innerText innerText返回文本信息
children://子元素集合
parentNode//父元素
总结:元素的功能属性直接可以通过元素对象点出来,除此意外的自定义属性,请通过get/setAtribute去操作

节点的查找:(最重要)

1、document.getElementById—根据id查找节点 [返回的是节点本身]

2、document.getElementsByTagName–根据标签名字来查找[返回的是数组]document.getElementsByTagName[i]

3、document.getElemenstByName–根据name属性来查找节点(一般用在表单中)[返回的是数组]document.getElemenstByName[i]

注意:早期浏览器都认为name只出现在表单中

因此document.getElemenstByName只对表单中的元素发挥作用 后来部分浏览器把Name属性扩展到一般的元素 如:div 但是IE浏览器还是只能对表单使用byName因此处于兼容性 我们只能对表单使用byName

4、查找子元素 children[index]/childNodes

5、查找父元素 node.parentNode –>获取父元素

6、查找兄弟元素 nextSibling previousSibling

7、nextSibling previousSibling firstChild lastChild这四个属性容易受到空白文本的影响 建议不用

事件(事故)基础

常用事件
onclick:当事件源被点击的时候调用处理程序
onmouseover:鼠标进入事件
onmouseout:鼠标移出事件
onmousedown:鼠标按下去的时候
onmouseup:鼠标抬起来的时候
onscroll:当事件源滚动条滚动的时候
onkeydown:当键盘按下的时候
onkeypress:当键盘按下去的时候
onkeyup:当键盘弹上来的时候
onfocus:当事件源获得光标
onblur:当事件源失去光标
onchange:当事件源blur的时候内容改变了的话