JS入门
一、JavaScript发展简史
JavaScript一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。它的解释器被称为JavaScript引擎,为浏览器的一部分,广泛用于客户端的脚本语言,最早是在HTML(标准通用标记语言下的一个应用)网页上使用,用来给HTML网页增加动态功能。
在1995年时,由Netscape公司的Brendan Eich,在网景导航者浏览器上首次设计实现而成。因为Netscape与Sun合作,Netscape管理层希望它外观看起来像Java,因此取名为JavaScript。但实际上它的语法风格与Self及Scheme较为接近。
为了取得技术优势,微软推出了JScript,CEnvi推出ScriptEase,与JavaScript同样可在浏览器上运行。为了统一规格,因为JavaScript兼容于ECMA标准,因此也称为ECMAScript。
二、CSS与JS的放置位置
-
CSS应放在页面顶部的
head
中
由于Rendering Tree是由DOM Tree和CSSOM Tree组合成的,html页面需要等到CSS解析完后才能完成渲染,所以CSS应放在head标签内,优先下载解析,以避免页面元素由于样式缺失造成白屏或FOUC。 -
JS应放在
body
的底部
因为浏览器需要一个稳定的DOM Tree结构,而且JS中很有可能有代码直接改变了其结构,浏览器为了防止出现JS修改DOM Tree,需要重新构建的情况,所以就会阻塞其他的下载和呈现。
将JS放在head
内和body
底部的区别也在于此:若放在head
里面,由于浏览器发现head
里面有JS标签就会暂时停止其他渲染行为,等待JavaScript下载并执行完成才能接着往下渲染,而这个时候将发生白屏;若放在body
底部,Rendering Tree已经完成大部分,所以此时页面有内容呈现,即使遇到JavaScript阻塞渲染,也不会有白屏出现。
三、JavaScript数据类型
- 数值(number):整数和小数
- 字符串(string):字符组成的文本
- 布尔值(boolean):true(真)和false(假)
- undefined:表示“未定义”或不存在,即此处目前没有任何值
- null:表示空值,即此处应该有一个值,但为空
- 对象(object):各种值组成的集合。对象有三个子类型狭义的对象(object),数组(array),函数(function)。
数值、字符串、布尔值称为原始类型(primitive type)值,即它们是最原始的数据类型,不能再细分了。而将对象称为复杂类型(complex type)值,因为一个对象往往是多个原始类型的值的合成,可以看作是一个存放各种值的容器。至于undefined和null,一般将它们看成两个特殊值。
四、typeof与instanceof
-
typeof
用于返回一个数据原始的数据类型。对于常见的几大数据类型都可以用typeof 数据类型
的方式进行判断(其中typeof null 返回的object)。 -
instanceof
用于判断某个对象是不是构造函数的一个实例,即一个新声明的变量是不是调用了构造函数的内置属性或方法。 - 对于一个变量a可用如下方法判断其数据类型:
type a === "number" \\判断a是否为数字
type a === "string" \\判断a是否为字符串
type a === "boolean" \\判断a是否为布尔值
type a === "function" \\判断a是否为函数
JS运算符
一、NaN的作用
-
NaN
不是数值,全称为Not a Number。它用于表示一个本来要返回数值的操作数未返回数值的情况,此时为了不报错,就会返回NaN
。 -
NaN
非常特殊,因为它“不是数字”,所以它不等于任何数,包括其自身,即NaN != NaN
。任何涉及NaN
的操作(如NaN/10
)都会返回NaN
这个特点在多步计算中有可能导致问题。 -
isNaN(testValue)
可检查一个参数是否为数值,返回true
或false
。
二、==与===
-
==
:相等运算符,但是不比较参数的类型,两边参数类型不同时,会先进行类型转化,再比较值。 -
===
:严格相等运算符,不仅比较参数的值,也比较参数的类型,只有两者均一致,才返回true
。
JS函数
一、if语句
- if语句的语法:
if(condition) {
statement
}else {
statement
}
其中的 condition可以是任意表达式;而且对这个表达式求值的结果不一定是布尔值。如果该位置是非布尔值,JavaScript会将这个值自动转为布尔值。
- condition判断:
- 布尔值:直接作出判断,true为true,flase为false
- 字符串:除了空字符串。
""
为false外,其余(包括包含空格字符串" "
)都为true。 - 数值:除了0(+0、-0、0.00、00等)与
NaN
为false,其余都为true。 - undefined:转换为false。
- null:转换为false
- 对象:转换为true(包括空数组
[]
与空对象{}
)
二、==相等操作符
相等操作符==
在比较两参数时,若参数类型不一致,会先将它们转换成一样的类型,再比较其相等性。转换规则如下:
- 若其中一个为布尔值,将其转换为数值,false为0,true为1;
- 若其中一个为字符串,另一个为数值,则将字符串转换为数值,只含数字的字符串转换为相应数字,空字符串或只含空格字符串转换为0,其余转换为
NaN
; - 若其中一个是对象,另一个不是,则调用对象的
valueOf()
方法,用前述规则进行比较;
以下特殊结果需特别注意:
null == undefined //true
NaN == NaN //false
false == undefined //fales
false == null //false
NaN != NaN //true
三、switch语句
- switch表达式如下:
switch(condition){
case 1:
statement1;
break;
case 2:
statement2;
break;
......
case N:
statementN;
break;
default:
statement;
}
switch语句会把condition与case进行对应,然后执行相应case的statement。
- break语句会在程序执行case后跳出当前的switch。若当前case没有break,程序会遍历当前case之后的case并执行statement,直到遇见break或遍历完所有的case,才跳出switch。
四、其他语句的用法
- while的用法:
var i = 5;
while(i>0){
console.log(i);
i--;
}
当()
中的条件为true时,程序会循环执行while中的语句,直到()
中的条件变为false。
- do-while的用法:
var i = 5;
do{
console.log(i);
i--;
}while(i>0)
do-while语句与while语句的用法大致相同,唯一不用的是,do-while会先执行do里的语句,再判断while的条件是否满足。
- for遍历数组的方法:
var arr = [3,4,5];
for(var i=0; i<3; i++){
console.log(arr[i])
}
- for-in遍历数组的方法:
var arr = [3,4,5];
for(var i in arr){
console.log(arr[i])
}
- break 和 continue 的用法:
for(var i = 0; i< 6; i++){
if(i % 4 === 0){
break;
}
console.log(i);
}
for(var i = 0; i< 6; i++){
if(i % 4 === 0){
continue;
}
console.log(i);
}
其中break语句会跳出整个循环,因此结果为不输出;continue语句会跳出当前循环,执行下一循环,因此结果为1 2 3 5。
JS作用域链与引用类型
一、立即执行函数
- 立即执行函数就是声明一个函数并马上调用它,
function
前后必须用小括号包裹起来。其语法如下:
( function(){
函数体
} ) ()
- 立即执行函数只有一个作用:创建一个独立的作用域,这个作用域里面的变量外面访问不到(即避免变量污染)。
二、作用域与作用域链
作用域
JS的作用域可分为全局作用域、函数作用域和块级作用域:
- 全局作用域:在全局对象(window)中声明的变量和函数具有全局作用域,程序的所有部位都可见。
- 函数作用域:在一个函数内部声明的变量和函数具有局部作用域,只在函数内部可见,若在函数外部访问会返回undefined。这里注意一点:带参的函数,参数列表中的参数也相当于是声明了的局部变量,在函数内部不需要再次声明,直接调用即可。若函数对象中和全局对象中同时对一个变量声明/赋值,在函数内部以函数内的声明/赋值为准。
- 块级作用域:用
let
/const
声明的变量只在{}
块级符号内部可见(es6新特性)。且const
是声明一个常量,在作用域内部不能改变,否则会报错。
作用域链
- 函数在执行的过程中,先从自己内部找变量
- 如果找不到,再从创建当前函数所在的作用域去找, 以此往上
- 注意找的是变量的当前的状态
可看如下例子:
var a = 1
function fn1(){
function fn2(){
console.log(a)
}
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
var fn = fn1()
fn() //输出2
var a = 1
function fn1(){
function fn3(){
var a = 4
fn2()
}
var a = 2
return fn3
}
function fn2(){
console.log(a)
}
var fn = fn1()
fn() //输出1
var a = 1
function fn1(){
function fn3(){
function fn2(){
console.log(a)
}
fn2()
var a = 4
}
var a = 2
return fn3
}
var fn = fn1()
fn() //输出undefined