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

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

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

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

JavaScript 很容易学习。

一、如何编写?

1.JavaScript代码存在形式

<!-- 方式一 -->
<script type="text/javascript" src="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

版权声明:本文为Javastudy-note原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/Javastudy-note/p/13811453.html