JS基础(二)JS入门

JS入门

1. JS的导入方式

与CSS类似JS也有自己的导入方式。(两种)

  1. 内部式
<!--在head或body中直接放入script标签在其中直接写JS文件-->
<head>
    <script>
        function getName(){
            
        }
    </script>
</head>
  1. 外部文件导入式
<!--在head或body中用script标签引入JS文件-->
<head>
    <script type="text/javascript" src=".js"></script>
</head>

不写script标签不写类型时,默认就是text/javascript。不管哪种导入方式,script标签在head和body中都可以使用,不像css的导入只能在head中。

2. JS调试

JS在浏览器中调试,在浏览器中按F12可以进入调试界面。

如图下图所示:

在这里插入图片描述

  • Element:是元素调试界面,所代表的是HTML文件的调试窗口。
  • Console:是控制台,可以调试、显示JS文件的执行结果。
    • 具体调试方法:1、使用alert弹窗进行文字的显示。2、console.log()进行打印。使用这两个方法时可以直接在Console控制台中那个蓝箭头直接输入调试,不必重新修改JS代码。
  • Sources:是资源控制台,在其中整个文件夹目录,可以在其中进行JS的逐步调试。它的调试方式与使用大多数编译器的调试一样,断点设置也是点击代码行数处。

3. JS语法

大家学习一门语言可以从它的使用角度来学习。比如我要写代码,我的代码中应该有哪些东西?如:变量、数据的类型、流程控制、运算符、函数(方法)等等一些在代码中可以看见的一些东西,这样就形成一个框架了。

严格检查模式

上文也说了,JS是一种非常不严格的语言,不管咋出错都不会报错。所以为了解决这一缺陷,在ES6中新增严格检查模式,不符合规则就报红。具体写法是:在代码最开头写上’use strict‘

'use strict';
var x = 12;
//这会报红因为没有声明这是一个局部变量
y = 10;

变量

变量的声明与作用域

变量有两种声明方式:

  • var:与let都是声明的局部变量,但是没有let严格。具体表现在for循环中使用var定义局部变量的话在退出for循环时仍会存留for循环中的局部变量。
  • let:let是ES6新特性。加强了变量的严格性。
  • 在局部中直接写变量不声明:不声明变量直接写变量名,会导致变量成为局部变量。

例如:

//变量的作用域是一个相对的概念,放在全局就是全局变量,放在局部就是局部变量
//全局变量,全局变量不能用let声明
var x = 1;

function getName(){
    var name = "lex";
    let name1 = "alex";
    //name2就是全局变量,因为没有声明var、let
    name2 = "hua";
}
变量空间的申请

变量有两种申请方式:

  • 使用var、let直接申请
var num = 1;
let name = "李四";
  • 使用new申请变量
var name = new String("李四");

两种申请方式的区别:

  • 使用前者申请的空间在栈内存中,后者申请的空间在堆内存中。
  • 与Java中的内存存储类似,但是不尽相同。
关于变量的一些规范

变量的名称:

  • 尽量与Java类似,使用驼峰式。(好像是)

全局变量的存放:

  • 为了使在引用多个JS文件时不会使全局变量之间冲突,将你自己写的全局变量存在你自己定义的全局变量对象中。这样调用全局变量时使用不同的全局变量对象进行调用使用。
  • 当你创建一个JS文件后,所有的全局变量都存在一个内置的全局变量对象window中。这也就意味着你可以从window中调用全局变量。

例如:

//注意只能用var声明全局变量,对象也算变量
var myValue = {};
myValue.name = "hhh";
myValue.age = 20;

//注意这里的age不与myValue中的age冲突,因为作用域不同。age在window对象中,myValue.age在myValue中,而myValue才在window中。
var age = 22;

这是一种规范,jQuery也是这么干的。比如:jQuery. 简化成了$( )(是等价的)。

JS的注释

JS有两种注释,与Java相同

  • //
  • /**/

JS数据类型

数字类型

number类型,共分为五类:整数、小数、使用科学计数法的数、NaN、Infinity。

  • 整数
var x = 1;

注意:在JS中 整数 / 整数 = 浮点数,只要商的话就将结果强制类型转换一下。

  • 小数
var x = 1.1;

注意JS中使用小数与Java中相同,要注意精度问题,根据问题的种类选择使用浮点数还是大数

  • 使用科学计数法的数
var x = 1e5;
  • NaN空值
var x = NaN;

注意:对于控制不可以使用比较运算符进行判断。要使用isNaN()这个函数。

//错误示范
var x = NaN;
if(x === NaN){
    
}

//正确示范
var x = NaN;
if(isNaN(x)){
    
}
  • Infinity无穷大
var x = Infinity;
字符串类型

字符串的声明

字符串使用单引号(‘ ’)或双引号(“ ”)来声明单行字符串,使用反引号声明多行字符串(``)

var name = 'lisi';
var sex = "man";
var p = `I am a
super man!`

注意:以上的字符串存在常量池中,是不可以改变的,要改变就new一个字符串。要声明到堆内存中则要使用new String。

反义字符

**反义字符与Java中相同。用反斜杠在前面。常用反义字符有:\n、\ ‘、\ "、\u####(使用Unicode字符集的####为四位二进制)、\x###(ASCII码的字符)**等等。

var x = "123\"xxx\n";

字符串的拼接

  • 模板字符串

    模板字符串用于字符变量与字符串的拼接,使用的是EL表达式

    模板字符串使用反引号 ,使用${x}拼接,如:

    var age = 21;
    var msg = `i am ${age}`;
    console.log(msg);
    
  • 使用+拼接字符串

var name = "lihua";
console.log(name+"is 11 years old");

字符串的一些方法(大部分与Java中相同)

  • length(长度)
var name = "lihua";
console.log(name.length);
  • substring(截取字符串)
var num = "123456789";
console.log(num.substring(0,4));
//输出1234
  • charAt(获取其中index的字符)
var x = "123";
console.log(x.chatAt(1));
//2
  • indexOf(获取第一次碰到字符或字符串的下标)
var x = "12345";
conlole.log(x.indexOf(2))
//1
  • toUpperCase(全变大写)
var x = "aaaa";
console.log(x.toUperCase());
  • toLowerCase(全变小写)
布尔类型
  • true
  • false
空指针类型
  • null:空,是为赋值的。
  • undefined:是为定义的。
数组类型

数组既是一种数据类型,也是一种容器。所以会有增删改查这些容器都具备的基本方法。

JS的数组与Java不同,因为不必声明数据类型所以可以存储不同类型的元素,并且数组的长度可变

数组的创建

使用中括号创建数组;

//不初始化
var array = [];

//初始化的声明
var array = [1, 2, 3, 'saq', "213"];

数组的访问

直接使用下标访问,若数组越界不会终止程序,会返回一个undefined

var x = [1,2,3,4,5];
console.log(x[2]);

数组变长

JS中的数组不像Java中的数组那么严格,长度是可以变的。

var x = [1,2,3];
x.length = 10;
//x会增加7个元素。

数组的一些重要方法

  • 增删
var arr = [];
//增
//增到尾
arr.push(1);
//增到头
arr.unshift(2);

//删
//删除尾
arr.pop();
//删除头
arr.shift();
  • indexOf(获取元素的下标)
var x = [1,2,3,4];
console.log(1);
//0
  • slice(截取部分元素,并形成新数组返回)
var x = [1,2,3,4];
var y = x.slice(0,2);
console.log(y)
//1 2
  • sort(将数组中的元素进行排序)
var x = [2,1,4,7,5];
x.sort();
//1,2,4,5,7
//排序默认升序排列,若要降序则可以自己定义一个比较器(一个函数)如:
var compare = function(obj1, obj2){
    if(obj1 > obj2)
        return 1;
    else
        return -1;
}
x.sort(compare);
  • reverse(倒转数组)
var x = [1,2,3,4];
consele.log(x);
//4 3 2 1
  • concat(拼接)
var x = [1,1,1];
var y = [2,2,2];
//返回一个新数组,不会修改原数组
var z = x.concat(y);
//1 1 1 2 2 2
  • join(使用连接符将数组拼接成字符串)
var x = [1,2,3,4];
var y = x.join("-");
console.log(y);
//1-2-3-4
对象类型

对象的创建

对象使用大括号({})声明,内部属性名与值之间用冒号表示(:),属性之间用逗号隔开、最后一个不写逗号。如:

var obj = {
    name:"lihua",
    age:12,
    tags:[2,3,4],
    get:function(){}
}

有些像python中的字典。

也可以直接引用函数作为方法:

function get(){
    return 1;
}
var obj = {
    name:"lihua",
    age:12,
    tags:[2,3,4],
    get:get
}

对象属性的访问

有两种访问方式:

  • 使用dot访问与添加(当对象中没有该元素时就添加,有就是修改)
var obj = {}
//因为没有该元素,所以就是添加
obj.name = "lihua"
//因为有该元素,所以是修改
obj['name'] = "lisi";
//访问属性
console.log(obj.name);
console.log(obj['name']);

对象可以动态的删除添加键值对。

ES6新容器

这些容器都是人写的新类,不是JS内置的数据类型。可以实现增删改查功能。

Map(增删改查)
//不初始化
Map map = new Map();
//初始化,使用二维数组初始化,内部数组为键值与值
Map map = new Map([['name', "lihua"], ['age', 14]]);

//增改,若找得到则修改,找不到就进行添加。
map.set('admain', 12345);
//删
map.delete('name');
//查
map.get('age');
Set(增删查)
//不初始化
Set set = new Set();
//初始化,使用一维数组进行初始化。这里初始化时有两个1,因为是集合所以只会有一个1多余的不会初始化进去。
Set set = new Set([1,2,3,1,5])

//因为集合不是数组,它是无序的所以不需要改,直接查看删除增加即可。
//增,增加元素。
set.add(6);
//删
set.delete(1);
//查,有则返回true。
set.has(3);
iterator迭代器

这些容器内置迭代器,所以可以用for of遍历它们。

Map map = new Map([['name', "lihua"], ['age', 14], ['tags', [1,2,34]]]);
for(let x of map){
    console.log(x);
    //x为每个键值对的值。
}

重要关键字(非很频繁)

indexof关键字

获取数据的数据类型使用:indexof xxx(indexof是关键字)

in关键字

使用in关键字可以判断某元素是否在数组或对象中。返回布尔类型

var x = [1,2,3,4];
var y = {
    name:"jjj",
    age:12
}
console.log(1 in x);
//in 在对象中只能判断是否有该键值,并且键值要写成字符串
console.log('name' in y);

运算符

算数运算符
  • /
  • %
  • ++
逻辑运算符
  • &&
  • ||
比较运算符
  • >
  • <
  • ==

对于两个等号的相等,只要值相等即可,不需类型相同。

  • !=

对于两个字符的相等,只要值不等即可,不需类型相同。

  • >=
  • <=
  • ===

强相等判断,必须值和类型都相等才能判断为真。

  • !==

强相等判断,必须值和类型都不等才能判断为真。

  • ?

三元运算符,与各种语言中的都一样。(没学过的话看我前面Java中的)

赋值运算符
  • =
  • +=
  • -=
  • %=
  • *=
  • /=
位运算符
  • &
  • |
  • ~
  • ^(按位异或)
  • >>
  • <<
  • >>>(零填充右移)
类型运算符
  • typeof(返回变量的类型)
  • instanceof(判断对象是否是某类或其子类的实例,与Java中相同)

流程控制

分支结构
if(x==1){
    
}else if(x==2){
    
}else{
    
}
switch(i){
case 1:...;break;
case 2:...;break;
case 3:...;break;
}
循环结构
while(){
     
}
do{
    
}while()

重要的for

普通for

for(int i = 0;i < 11;i++){
    
}

for in

for(let x in array){
    //对象也可以。x为后面的下标
}

for of

for(let x of array){
    //对象也可以。x为后面的值。这使用的是迭代器。
}

forEach

array.forEach(function(value){
    //value是正在进行迭代的元素的值。
});

总结for:1.普通for,i为额外变量值。2.for in,变量为元素下标。3.for of,本质用的是迭代器,变量为元素的值。4.forEach,是一个函数,用在对象或数组上,参数是一个函数,函数中的参数是当前迭代的元素的值。


模块化

因为代码大多数都是共用的,为了减少代码冗余进行模块化。

函数(函数也是一种类型,可以typeof)

函数使用function声明,函数由function关键字、函数名、参数列表、函数体构成。与python相同,函数可以看成变量,是可以赋值的。

函数的声明

  • 有名函数
function getName(){
    retutn 1;
}
  • 匿名函数
var getName = function(){
    retutn 1;
}
getName();

函数的参数

  • 因为JS中没有显示声明的数据类型,所以函数中参数是不用声明数据类型的,也就把var给省略了。
function getName(name, age){
    return name;
}
  • 实参列表对象:arguments

arguments是一个实参列表对象(实际上就是一个数组,存着实参们),每一个函数都有一个arguments。在函数体中可以使用

为什么会有实参列表对象呢?直接用形参列表不可以吗?因为JS的不严谨性,使得实参多于或少于形参都不会报错,所以出现实参列表对象。当形参多余实参时,多余的参数是undefined

function getName(x1, x2, x3){
    if(x1 != undefined && x2 != undefined && x3 != undefined){
        console.log(arguments.length);
    }
}
getName(1,1,1,1);
//输出4
  • 可变长参数:…rest

在Java中可有可变长参数,但是Java中你可以自定义参数名,JS的可变长参数的参数名只能是rest。

实参列表对象用于确定总共有多少参数,且参数的值是啥。而可变长参数用来判断多余的、尾部的参数们是啥。

function getLength(x1, x2, x3, ...rest){
    console.log("多余的参数有"+rest.length+"个");
}
类与对象
对象

对象的两种定义方式:

  • 直接创建对象
var obj = {
    name:"小红",
    get:function(){
        return this.name;
    }
}

这种方式创建的对象是一次性的,不像使用类还可以多次创建同种类型的对象。

  • 使用类new对象
var string = new String();

当然,这种方式也有限制。只有ES6以后的才能只用。因为类在ES6中提出的。

this指针的注意事项:

学习过多种面向对象语言就会非常熟悉this指针。在对象内this指针指向对象本身。但是在JS中全局函数中有this指针也是可以的。因为全局变量存在window对象中(函数也是一个变量)。所以全局函数中的this指针指向window对象。

例如:

var x = 3;

var getX = function(){
    return this.x;
}

var value = {
    x:1,
    get:getX
}

value.get();//输出1
getX();//输出3,相当于window.getX(),全局变量中也有一个x变量3

封装:

类是ES6的新特性,使用方法与Java类似,只不过构造函数写法不同。

例如:

class Test{
    let x1;
    let x2;
    //构造函数
    constructor(x1, x2){
        this.x1 = x1;
        this.x2 = x2;
    }
}

var test = new Test(1, 2);

继承:

JS的继承与Java相同,使用extends关键字进行继承。在子类的构造函数中构造父类使用super( )。

例如:

class Test{
    let x1;
    let x2;
    //构造函数
    constructor(x1, x2){
        this.x1 = x1;
        this.x2 = x2;
    }
}

class TwoTest extends Test{
    constructor(x1, x2){
        super(x1, x2);
        console.log("I'am TwoTest");
    }
}

对于继承而言,与Java不同的是:Java的继承形成的是继承树,但是JS的继承形成的是一个链。在浏览器的元素审查列表可以看见JS的父类是点不完的,而且有套娃的现象。

在ES6之前,对于继承这个操作,JS使用的是一种叫原型的东西。也就是定义了一个对象,另一个对象与它相似,那么就以前者为原型进行重构。__proto__可以查看原型。

多态:

在JS中因为没有明确声明数据类型的变量,所以对于像Java中父类引用指向子类对象这一多态操作是行不通的。在JS中使用了apply函数进行多态,每个函数都有这个函数。(也就是可以调用apply函数。有人可能会问为什么函数还能调用函数?不要忘记之间说过的在JS中函数也是变量,如果学过python肯定对这个概念有深刻体会。

使用方法:function_x.apply(obj, [ ])。

  • function_x是要进行多态的函数,也就是对于多个对象使用这个函数会有不同的行为。
  • obj是指向对象,本质上是改变this指针的指向。
  • [ ],这个数组是参数列表。如果function_x无参直接用一个空数组[]即可,有参数组中添加参数即可,例如:[x1, x2]
class One{
    function print(){
        console.log("I'am One");
    }
}

class Two{
    function print(){
        console.log("I'am Two");
    }
}

var one = new One();
var two = new Two();
var list = [one, two];

for(let x of list){
    print.apply(x, []);
}

/*
输出:
I'am One
I'am Two
*/

class TwoTest extends Test{
constructor(x1, x2){
super(x1, x2);
console.log(“I’am TwoTest”);
}
}


  **对于继承而言,与Java不同的是:Java的继承形成的是继承树,但是JS的继承形成的是一个链。在浏览器的元素审查列表可以看见JS的父类是点不完的,而且有套娃的现象。**

  **在ES6之前,对于继承这个操作,JS使用的是一种叫原型的东西。也就是定义了一个对象,另一个对象与它相似,那么就以前者为原型进行重构。__proto__可以查看原型。**



**多态:**

  在JS中因为没有明确声明数据类型的变量,所以对于像Java中父类引用指向子类对象这一多态操作是行不通的。在JS中使用了apply函数进行多态,每个函数都有这个函数。(也就是可以调用apply函数。有人可能会问为什么函数还能调用函数?**不要忘记之间说过的在JS中函数也是变量,如果学过python肯定对这个概念有深刻体会。**)

  **使用方法:function_x.apply(obj, [ ])。**

* function_x是要进行多态的函数,也就是对于多个对象使用这个函数会有不同的行为。
* obj是指向对象,本质上是改变this指针的指向。
* [ ],这个数组是参数列表。如果function_x无参直接用一个空数组[]即可,有参数组中添加参数即可,例如:[x1, x2]

```javascript
class One{
    function print(){
        console.log("I'am One");
    }
}

class Two{
    function print(){
        console.log("I'am Two");
    }
}

var one = new One();
var two = new Two();
var list = [one, two];

for(let x of list){
    print.apply(x, []);
}

/*
输出:
I'am One
I'am Two
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值