首页 > 代码库 > web前端基础知识-(三)JavaScript基本操作

web前端基础知识-(三)JavaScript基本操作

JavaScript 是一种轻量级的编程语言。

JavaScript 是可插入 HTML 页面的编程代码。

JavaScript 插入 HTML 页面后,可由所有的现代浏览器执行。

JavaScript 很容易学习。

一、如何编写?

1.JavaScript代码存在形式

<!-- 方式一 -->
<script type="text/javascript" src="http://www.mamicode.com/JS文件"></script>
  
<!-- 方式二 -->
<script type="text/javascript">
    Js代码内容
</script> 

2.JavaScript存放位置 

HTML 中的脚本必须位于 <script> 与 </script> 标签之间。 

脚本可被放置在 HTML 页面的 <body> 和 <head> 部分中。

由于Html代码是从上到下执行,如果Head中的js代码耗时严重,就会导致用户长时间无法看到页面,如果放置在body代码块底部,那么即使js代码耗时严重,也不会影响用户看到页面效果,只是js实现特效慢而已。

这里,推荐放在body体底部;

3.注释

JavaScript 不会执行注释。

我们可以添加注释来对 JavaScript 进行解释,或者提高代码的可读性。

单行注释以 // 开头。

// 输出标题:
document.getElementById("myH1").innerHTML="欢迎来到我的主页";
// 输出段落:
document.getElementById("myP").innerHTML="这是我的第一个段落。";

多行注释以 /* 开始,以 */ 结尾。

/*
下面的这些代码会输出
一个标题和一个段落
并将代表主页的开始
*/

二、变量

JavaScript中变量的声明是一个非常容易出错的点,局部变量必须一个 var 开头,如果未使用var,则默认表示声明的是全局变量。

JavaScript 变量可用于存放值(比如 x=5)和表达式(比如 z=x+y)。

var x=5;
var y=6;
var z=x+y;

变量可以使用短名称(比如 x 和 y),也可以使用描述性更好的名称(比如 age, sum, totalvolume)。

  • 变量必须以字母开头
  • 变量也能以 $ 和 _ 符号开头(不过我们不推荐这么做)
  • 变量名称对大小写敏感(y 和 Y 是不同的变量)

JavaScript 语句和 JavaScript 变量都对大小写敏感。

<script type="text/javascript">
 
    // 全局变量
    name = ‘seven‘;
 
    function func(){
        // 局部变量
        var age = 18;
 
        // 全局变量
        gender = "男"
    }
</script>

三、数据类型 

JavaScript 中的数据类型分为原始类型和对象类型:

  • 原始类型
    • 数字
    • 字符串
    • 布尔值
  • 对象类型
    • 数组
    • 字典
    • ...

1.数字

JavaScript中不区分整数值和浮点数值,JavaScript中所有数字均用浮点数值表示。

转换:

  • parseInt(..)    将某值转换成数字,不成功则NaN
  • parseFloat(..) 将某值转换成浮点数,不成功则NaN

特殊值:

  •  NaN,非数字。可使用 isNaN(num) 来判断。
  • Infinity,无穷大。可使用 isFinite(num) 来判断。

2.字符串

字符串是由字符组成的数组,但在JavaScript中字符串是不可变的:可以访问字符串任意位置的文本,但是JavaScript并未提供修改已知字符串内容的方法。

常见功能:

obj.length 获取当前字符串长度
obj.trim() 移除空白
obj.trimLeft()
obj.trimRight)
obj.charAt(n) 返回字符串中的第n个字符
obj.concat(value, ...) 拼接
obj.indexOf(substring,start) 子序列位置
obj.lastIndexOf(substring,start) 子序列位置
obj.substring(from, to) 根据索引获取子序列---起始位置,结束位置
obj.slice(start, end) 切片
obj.toLowerCase() 大写
obj.toUpperCase() 小写
obj.split(delimiter, limit) 分割
obj.search(regexp) 从头开始匹配,返回匹配成功的第一个位置(g无效)
obj.match(regexp) 全局搜索,如果正则中有g表示找到全部,否则只找到第一个。
obj.replace(regexp, replacement) 替换,正则中有g则替换所有,否则只替换第一个匹配项,
$数字:匹配的第n个组内容;
$&:当前匹配的内容;
$`:位于匹配子串左侧的文本;
$‘:位于匹配子串右侧的文本
$$:直接量$符号

3.布尔类型

布尔类型仅包含真假,与Python不同的是其首字母小写。

  • ==      比较值相等
  • !=       不等于
  • ===   比较值和类型相等
  • !==    不等于
  • ||        或
  • &&    且

4.数组

JavaScript中的数组类似于Python中的列表。

常见功能:

obj.length          数组的大小
obj.push(ele)       尾部追加元素
obj.pop()           尾部获取一个元素
obj.unshift(ele)    头部插入元素
obj.shift()         头部移除元素
obj.splice(start, deleteCount, value, ...)  插入、删除或替换数组的元素
                    obj.splice(n,0,val) 指定位置插入元素
                    obj.splice(n,1,val) 指定位置替换元素
                    obj.splice(n,1)     指定位置删除元素
obj.slice( )        切片
obj.reverse( )      反转
obj.join(sep)       将数组元素连接起来以构建一个字符串
obj.concat(val,..)  连接数组
obj.sort( )         对数组元素进行排序

四、小知识汇总

1. 序列化

序列化就是将JavaScript中的数据类型转换成字符串,反序列化的过程则相反;

var a="ss";
ret = JSON.stringify(a);//序列化
console.log(ret);

console.log(JSON.parse(ret));//反序列化

结果如下:

技术分享

2. 转义

一般使用在URL中字符的转义等,下面来看一下具体的用法

var a=‘http://www.baidu.com?name=民资‘;
console.log(encodeURI(a));
console.log(decodeURI(encodeURI(a)));
console.log(encodeURIComponent(a));
console.log(decodeURIComponent(encodeURIComponent(a)));

结果如下:

技术分享

3. eval

JavaScript中的eval是Python中eval和exec的合集,既可以编译代码也可以获取返回值。

console.log(eval(‘1+2*5‘)); 
console.log(eval(a = 1));    

结果如下:

技术分享

4. 时间

在JavaScript中,Date对象用来表示日期和时间。JavaScript中提供了时间相关的操作,分别为获取时间和设置时间,时间操作中分为两种时间,统一时间(UTC),以及本地时间(东8区)

var now = new Date();
now.getFullYear(); //2016
now.getMonth(); // 月份,注意月份范围是0~11,6表示7月
now.getDate(); // 日期
now.getDay(); // 表示星期几
now.getHours(); // 24小时制
now.getMinutes(); // 分钟
now.getTime(); // 以number形式表示的时间戳

结果如下:

技术分享

五、循环和条件语句

1. 条件语句

  if(条件){
  
    }else if(条件){
          
    }else{
  
    }
 
 
switch(name){
        case ‘1‘:
            age = 123;
            break;
        case ‘2‘:
            age = 456;
            break;
        default :
            age = 777;
    }

2.for循环和while循环

for循环

循环时,循环的元素是索引

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <script>
        var names = ["cc", "tony", "rain"];
        for(var i=0;i<names.length;i++){
            console.log(i);
            console.log(names[i]);
        }
    </script>
</body>
</html>

执行结果:

技术分享

while循环,同python中的while循环

 while(条件){
        
        
        }

五、函数

1.函数类型

JavaScript中函数基本上可以分为以下三类:普通函数,匿名函数,自执行函数。

此外需要注意的是对于JavaScript中函数参数,实际参数的个数可能小于形式参数的个数,函数内的特殊值arguments中封装了所有实际参数。

//函数
        function func(arg){
        
            return arg+1
        }
        var result = func(1)
        console.log(result);

//普通函数:
    function func(){
        
    }
//匿名函数:
    
    function func(arg){
    
        return arg+1
    }
    
    setInterval("func()", 5000);
    
    setInterval(function(){
        console.log(123);
    
    },5000)
    
//自执行函数(创建函数并且自动执行):
    (function(arg){
        console.log(arg);
    })(1)        
//自执行函数等同于以下代码:
    function func(arg){
        console.log(arg);
    }
    func(1)
    

2.函数作用域

作用域在许多程序设计语言中非常重要。

通常来说,一段程序代码中所用到的名字并不总是有效/可用的,而限定这个名字的可用性的代码范围就是这个名字的作用域。

作用域的使用提高了程序逻辑的局部性,增强程序的可靠性,减少名字冲突。

首先,了解下其他语言的作用域:

  • 其他语言:以代码块为作用域
public void Func(){
                        if(1==1){
                            string name = ‘Java‘;
                            
                        }
                        console.writeline(name);
                        
                    }
                    Func()
                    // 报错
  • python:以函数作为作用域
情况一:
    def func():
        if 1==1:
            name = ‘alex‘
        print(name)
        
    func()
    // 成功
情况二:
    def func():
        if 1==1:
            name = ‘alex‘
        print(name)
        
    func()
    print(name)
    // 报错

而javascript的作用域具有如下特点:

2.1 以函数作为作用域

先看下以下代码:

var name=‘cc‘;
function func(){
    console.log(name);
    if(1==1){
        var name = ‘dd‘;
    }
    console.log(name);
}
func()

第一句输出的是:undefined,而不是cc;

第二句输出的是:dd

大家可能认为第一句会输出cc,因为代码还未执行var name=‘dd‘;所以肯定会输出cc;

上面我们已经说过,javascript是以函数作为作用域。实际上以上代码可重新编写:

var name=‘cc‘;
function func(){
    var name;
    console.log(name);
    if(1==1){
        var name = ‘dd‘;
    }
    console.log(name);
}
func()

name声明覆盖了全局的name,但还没有赋值,所以输出undefined;

2.2 函数的作用域在函数未被调用之前,已经创建

function func(){
    if(1==1){
        var name = ‘cc‘;
    }
    console.log(name);
}

2.3 函数的作用域存在作用域链,并且也是在被调用之前创建

我们来看第一个例子:

xo = "cc";
function func(){
    var xo = ‘eric‘;
    function inner(){
        var xo = ‘tony‘;
        console.log(xo);
    }
    
    inner()
}

func()

输出:tony;

注释掉var xo=‘tony‘;一行,输出:eric;

同时注释掉var xo=‘tony‘;和var xo=‘eric‘;输出cc;

示例二:
    xo = "cc";
    
    function func(){
        var xo = ‘eric‘;
        function inner(){
            
            console.log(xo);
        }
        
        return inner;
    }
    
    var ret = func()
    ret()

示例三:
    xo = "alex";
    
    function func(){
        var xo = ‘eric‘;
        function inner(){
            
            console.log(xo);
        }
        var xo = ‘tony‘;
        
        return inner;
    }
    
    var ret = func()
    ret()

2.4 函数内局部变量声明提前

function func(){
    console.log(name);
}

func();
// 程序直接报错

function func(){
    console.log(name);
    var name = ‘cc‘;
}
//解释过程中:var name;

func();
// undefined

3. javascript高级知识-词法分析

js运行前有一个类似编译的过程即词法分析,词法分析主要有三个步骤:

  • 分析参数;

  • 再分析变量的声明;

  • 分析函数说明;

具体步骤如下:

  • 函数在运行的瞬间,生成一个活动对象(Active Object),简称AO;

  • 分析参数

  1. 函数接收形式参数,添加到AO的属性,并且这个时候值为undefine,例如AO.age=undefined;

  2. 接收实参,添加到AO的属性,覆盖之前的undefined;

  • 分析变量声明,如var age;或var age=23;

  1. 如果上一步分析参数中AO还没有age属性,则添加AO属性为undefined,即AO.age=undefined;

  2. 如果AO上面已经有age属性了,则不作任何修改;

  • 分析函数的声明,如果有function age(){};把函数赋给AO.age ,覆盖上一步分析的值;

这样说可能大家不是很理解,下面结合具体的例子看下:

3.1 例1:

<script>
    function t1(age) {
        console.log(age);
        var age = 27;
        console.log(age);
        function age() {}
        console.log(age);
    }
    t1(3);
</script>

词法分析阶段:

1)首先形成active object对象,即AO对象;

2)第一步分析形参:

AO.age=undefined;

传入实参即对AO.age=undefined进行覆盖:AO.age=3;

3)第二步分析局部变量:

存在var age=27;

这个时候遵循如果AO.age存在值则不作任何修改.按照第一步分析的最后结果AO.age = 3,所以这里不作任何修改即:AO.age = 3

4)第三步:分析函数的声明:

因为函数中存在function age(){}函数

所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 3即:

AO.age = function age(){}

执行阶段:

执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:

function age(){}

var age=27;给age赋值27

到第二个console.log(age)这个时候age已经重新被赋值27,所以这个时候会打印:

27

function age() 并没有调用所以并不会执行

到第三个console.log(age)这个时候age的值并没有被再次修改,所以这个时候会打印:

27 

运行js查看结果如下与我们分析的完全相符:

技术分享

3.2 代码例子2:

function t1(age) {
        var age;
        console.log(age);
        var age = 23;
        console.log(age);
        function age() {}
        console.log(age);
    }
t1(22)

词法分析阶段:

  • 首先形成Active Object即AO对象

  • 第一步:分析形式参数

AO.age = undefine

传入实参即对AO.age=undefine进行覆盖:

AO.age = 22

  • 第二步:分析局部变量

第一步中最后得到AO.age = 22

所以这里var age;以及var age =23 ,因为AO.age属性已经存在值,所以这个时候遵循如果存在则不作任何修改,即:

AO.age = 22

  • 第三步:分析函数的声明,

因为函数中存在function age(){}函数

所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 22即:

AO.age = function age(){}

执行阶段:

执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){},所以会打印:

function age(){}

var age=23;给age赋值23

到第二个console.log(age)这个时候age已经重新被赋值23,所以这个时候会打印:

23

function age() 并没有调用所以并不会执行

到第三个console.log(age)这个时候age的值并没有被再次修改,所以这个时候会打印:

23

运行js查看结果如下与我们分析的完全相符:

技术分享

3.3 代码例子3

function t1(age) {
    var age;
    console.log(age);
    age = 23;
    console.log(age);
    function age() {
        console.log(age);
    }
    age();
    console.log(age)
}
t1(22)

词法分析阶段:

  • 首先形成Active Object即AO对象

  • 第一步:分析形式参数

AO.age = undefine

传入实参即对AO.age=undefine进行覆盖:

AO.age = 22

  • 第二步:分析局部变量

第一步中最后得到AO.age = 22,所以这里遵循,如果AO.age存在值则不作任何修改即:

AO.age = 22

  • 第三步:分析函数的声明

因为函数中存在function age(){console.log(age)}函数

所以按照规则应该将函数赋值给AO.age覆盖第二步分析的AO.age = 22即:

AO.age = function age(){console.log(age)}

执行阶段:

执行t1函数,到console.log(age)时,词法分析的最后AO.age= function age(){console.log(age)},所以会打印:

function age(){console.log(age)}

age = 23,这个时候会覆盖原来的function age(){console.log(age)},所以第二个console.log(age)会打印:

23

function age() 是一个函数表达式,所以不会做任何操作

age() 这个时候的age还是23,并不是函数表达式,所以这里会报错

运行js查看结果如下与我们分析的完全相符:

技术分享

六、面向对象

1. 创建对象

function Foo(n){ //构造函数
    this.name = n;//this等同于python面向对象的self
    this.sayName = function(){
        console.log(this.name);
    }
}
var obj1 = new Foo(‘we‘); //要创建对象的实例必须要用new操作符
obj1.name
obj1.sayName()
var obj2 = new Foo(‘wee‘); //obj1 obj2都是Foo对象的实例
obj2.name
obj2.sayName()

构造函数的缺点:使用构造函数创建每个实例的时候,构造函数里的方法都要在每个实例上重新创建一遍,这样会浪费内存;

2. 原型

为了解决上述问题,javascript引入了一个prototype-原型;

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个对象;

用途:包含可以由特定类型的所有实例共享的属性和方法;

理解:prototype是通过调用构造函数创建的那个对象的原型对象;

使用原型的好处是可以让所有对象实例共享它所包含的属性和方法;

也就是说,不必在构造函数中定义对象信息(属性/方法),而是可以直接将这些信息添加到原型中;

function Foo(n){
    this.name = n;
}
# Foo的原型
Foo.prototype = {
    ‘sayName‘: function(){
        console.log(this.name)
    }
}

obj1 = new Foo(‘we‘);
obj1.sayName()

obj2 = new Foo(‘wee‘);

具体可参照http://www.jb51.net/article/63876.htm

web前端基础知识-(三)JavaScript基本操作