JavaScript(JS)学习笔记,通俗易懂,进阶之路

基础数据类型

  • Number,数值类型,包含整数和浮点数。其中包含一个特殊的数值类型NaN,它表示一个非数值类型的数值,但它的数据类型属于数值类型。
  • Boolean,布尔值,true和false
  • String,字符串
  • undefined,内置的一个特殊类型,表示未定的类型
  • null,内置的一个特殊类型,表示对象为null(空)

注:基础数据类型的值不可变。如果赋值,其实是重新创建一个新的对象。

字符串

substr(a,b)

从下标a位开始截取,共截取b个长度的字符;

substring(a,b)

从下表a未开始截取,共截取b-a个长度的字符,包含a小标不包含b下标的字符;

str[0]

可以直接从字符串中获取指定下表的字符,一个字符串可以当字符数组使用;

indexOf(a)

获取字符串指定下标的字符;

length

返回字符串长度。无法更改

流程控制

if判断

java用法一致。

循环

以下3个循环与java中的用法一致。

  • for循环

  • while循环

  • **do{}while()**循环

JavaScript特有的循环

forEach 循环。

有2中循环方式,只是传入的函数参数不同(1个或3个)。

//forEach 循环标准写法,传入一个函数,用于执行循环体
// 第一种,只传入一个参数,则该参数的值为数组的值
let ints = [1,2,4,5,6,7,8,9,23,12,125,89];
ints.forEach(function (value) {
    console.log(value);
});

//forEach循环,传入的函数为3个参数时,则参数分别为当前循环的值,当前循环的下标和数组本身
ints.forEach(function (value, index, array) {
    console.log('value:'+value+',index:'+index+',array:'+array);
})

//传入的函数可以简写,类似于java中的 lambda 表达式
ints.forEach(value => console.log(value));

ints.forEach((value, index, array) => console.log('value:'+value+',index:'+index+',array:'+array));

for in 循环。

注:for in 循环中,循环的得到的变量为数组的下标。

// 其中的 index 为数组的下标
for (const index in ints) {
    console.log('index:' + index + ', value=' + ints[index]);
}

for of 循环

注:for of 循环中,循环的得到的变量为数组中实际的值。

// 其中的 value 为数组的实际值
for (const value of ints) {
    console.log('value=' + value);
}

Map和Set

Map

存储一个键值对[key, value]对象的集合容器,且其中的key不能重复,如果key相同,则覆盖旧的对象。与java中的map基本类似。

//定义map,并传入一个数组来初始化内容
let map1 = new Map([['a',22],['b',23],['c',24]]);
//从map中获取数据
console.log(map1.get('a'));
//向map添加数据
map1.set('e', 12);
//删除map中的数据
map1.delete('c');
//判断某个key是否存在
map1.has("d");

//map遍历1
console.log('map.forEach()-------------');
map1.forEach(value => console.log(value));
map1.forEach((value, key) => console.log(value + ',' + key));
map1.forEach((value, key, map) => console.log(value + ',' + key + ',' + map));
//map遍历2,迭代器
console.log('map.entries()-------------');
for (const entry of map1.entries()) {
    //其中的 entry 为map中一个元素的数组形式,如:[key,value]
    console.log(entry[0] + ', ' + entry[1]);
};

//map特殊遍历1,key 的遍历
console.log('map.keys()-------------');
for (const key of map1.keys()) {
    console.log(key);
};
//map特殊遍历2,value 的遍历
console.log('map.values()-------------');
for (const value of map1.values()) {
    console.log(value);
};

Set

存储一个无序不重复的集合容器。与java中的Set基本类似。

//Set,创建,并初始化数据
let set1 = new Set([1, 1, 1, 2, 2, 3, 4, 5, 5, 6]);
//添加元素
set1.add(3);
//删除元素
set1.delete(6);
//判断是否存在指定的元素
set1.has(6);
//循环
console.log('set.forEach()-------------');
set1.forEach(value => console.log(value));
set1.forEach((value, value2) => console.log(value + ', ' + value2));
set1.forEach((value, value2, set) => console.log(value + ', ' + value2 + ', ' + set));
console.log('for of set ()-------------');
for (let value of set1) {
    console.log(value);
}
console.log('for of set.values()-------------');
for (let value of set1.values()) {
    console.log(value);
}
console.log('for of set.entries()-------------');
for (const entry of set1.entries()) {
    //其中的 entry 为map中一个元素的数组形式,如:[key,value],而在set中,返回的数组entry数组的key和value是一样的
    console.log(entry[0] + ', ' + entry[1]);
};

函数

定义函数

//定义函数1,标准写法
function abs1(x) {
    if (x > 0) {
        return x;
    } else {
        return -x;
    }
}

//定义函数2,类似与java的匿名类
let abs2 = function (x) {
    if (x > 0) {
        return x;
    } else {
        return -x;
    }
}

调用函数

//直接调用即可,2者调用方式一样
abs1(10);
abs2(10);

函数内置的对象

arguments

arguments是函数内置的一个对象,用于表示实际调用该函数时所传入的参数一个数组。数组的内容为传入的参数的值,数组的长度为传入的参数的个数。

注:在JavaScript中,调用函数时,可以传入任意个数的参数,不管被调用的函数定义时有几个参数。

//函数内置的 arguments 测试
function f1(x) {
    let len = arguments.length;
    console.log('arguments.length:' + len);
    for (let i = 0; i < len; i++) {
        console.log(arguments[i]);
    }
};

//调用函数,传入特意个数的参数,此时,arguments.length=3,并且会打印出3个参数的内容
f1(1, 2, 43);

rest 可变长度参数

reset是在函数定义时使用可变参数的一种语(其实只是可变参数的一种官方叫法,并不属于关键字),其格式为:…参数名。当调用函数时传入的参数个数超过函数所定义的参数个数,则按顺序将值赋值给对应参数,剩余的参数全部由可变参数来接受,成为一个数组,结构与函数内置的arguments对象类似。

注:可变参数必须写在函数参数列表中最后一个,一个函数也可以没有其它参数,有且仅有一个可变参数,如:function fun(…params)。

//rest 可变参数测试
function f2(a, b, ...params) {
    let len1 = arguments.length;
    console.log('arguments.length:' + len1);
    for (let i = 0; i < len1; i++) {
        //会打印所有参数
        console.log(arguments[i]);
    }

    let len2 = params.length;
    console.log('params.length:' + len2);
    for (let i = 0; i < len2; i++) {
        //只打印a,b参数之后的参数
        console.log(params[i]);
    }
};

//调用函数后,函数的参数值更别为:a=1,b=2,params=[4,7,9]
f2(1, 2, 4, 7, 9);

变量

定义变量

在JavaScript中定义变量不需要指明数据类型,而是在执行时JavaScript引擎动态的判断数据类型。

在定义时,使用varlet来定义变量,如:var a =1; let b=‘A’;。

JS执行引擎在执行时,会将代码块中的所有定义变量自动提取到代码块内的第一行,但只是将定义移动到第一行,给变量的赋值的代码的位置是不会变的。因此在js中,哪怕一个变量在代码块后面才声明,但是在前面仍然可以使用,只是在前面使用时,它的值为undefined。例如:

function f1(){
    let a=1;
    console.log(a);
    let b='a';
}
//实际js引擎在执行时,会将代码调整为如下顺序
function f1(){
    let a,b;
    a=1;
    console.log(a);
    b='a';
}

建议:将所有变量都放在代码块内第一行,能赋值的就在定义时直接赋值,不能赋值的就只做定义。这样可能有利于提高js的性能。

var 与 let 区别

var 关键字在定义变量后,出了当前内部的代码块仍然可以使用,作用域比较大。

function f1() {
    //使用var在循环内定义的变量i
    for (var i = 0; i < 3; i++) {
        console.log(`inner for:` + i);
    }
    //出了循环后,仍然可以使用变量i,但是仅限在函数f1()内可以用,除了函数则无法使用变量i
    console.log(`outer for:` + i);
};
f1();

let 关键字在定义变量后,则只在所定义的代码块中有效,作用域比较小。

function f2() {
    //使用let在循环内定义的变量j
    for (let j = 0; j < 3; j++) {
        console.log(`inner for:` + j);
    }
    //出了循环后,则无法在使用变量j,此语句会报错:Uncaught ReferenceError: i is not defined
    console.log(`outer for:` + j);
};
f2();

建议:尽量使用let来定义变量,已降低变量的作用域。

只读变量(常量)

只读变量也叫常量,它只能在定义时进行一次赋值,之后则不能再进行赋值。它使用关键字 const 来定义

//定义一个常量,且必须进行赋值
const PI=3.14159;
//常量无法进行第二次赋值,此语句会报错:Uncaught TypeError: Assignment to constant variable.
// PI = 2222;

全局变量

全局变量默认绑定在window下。js实际上只有一个全局作用域——window,任何全局变量都会绑定到window对象下。如:

//定义了一个全局变量
var a=1;
function f1(){
    console.log(a);
}
consloe.log(a)
//通过window对象也可以访问a,因此说明全局变量默认都绑定在window对象下
window.a;

建议:由于全局变量都是绑定到window下,因此很容易导致变量冲突,因此产生了一种约定成熟规范。使用一个自己的全局对象变量,然后在该全局对象变量中进行属性的增删改查操作。如:

//定义一个全局变量对象
var MY_APP_INFO = {};

//然后在其它地方使用时,则只是对该全局对象变量的属性进行操作
MY_APP_INFO.name = 'aaaaa';
MY_APP_INFO.fun1 = function(a,b){.....};
....

方法

在对象中,只会包含属性和方法。

//定义一个对象,该对象包含属性和方法
let person = {
    name: 'billy',
    birth: 1990,
    //定一个对象的方法
    age: function () {
        let year = new Date().getFullYear();
        //此处的this表示person这个对象本身
        return year - this.birth;
    }
};

function getAge() {
    let year = new Date().getFullYear();
    //此处的this默认情况下表示调用该函数的那个对象
    return year - this.birth;
};

//此时调用,则该函数中的this则指向window对象
getAge();

//定义一个对象,该对象包含属性和方法
let man = {
    name: 'man billy',
    birth: 2000,
    //定义个一个方法,该方法指向外部的一个函数
    age: getAge
}

this

默认指向

注:在函数中使用 this 关键字时,默认指向为调用该函数的对象。

更改 this 指向

若想在调用函数时,更改 this 的指向,则需要用到函数的 apply()方法。

//在js中可以通过调用函数的 apply()方法来指定函数体内使用的this指向,下雨的语句则显示的把函数中this的指向了person对象,因此返回结果为30
let age = getAge.apply(person);
console.log(age);

注:apply()方法有多个参数,若调用的函数需要传入参数,则可以添加参数。如:fun1.apply(obj,a,b.....)

对象

用户对象

定义对象

以大括号包括,对象里面以键值对的形式进行赋值,每个键值对中间用逗号隔开,最后一个键值对不用逗号。

let person={
    name:'billy',
    age:18,
    email:'234234@qq.com'
}

修改对象属性

person.name = 'jgl'

注:若访问对象的一个属性不存在,也不会报错,只是返回undefined

删除对象属性

//删除person对象的emial属性
delete person.email

注:若删除一个对象不存在的属性,也不会报错,仍然会返回true。

增加对象属性

// 直接添加新属性
person.hhhh = '新属性';

判断对象是否包含某个属性

使用in
// 判断person中是否存在age属性,返回true
'age' in person;
// 继承至Object,因此也包含toString方法
'toString' in person;
使用hasOwnProperty()

xxx.hasOwnProperty('xxx')用于判断对象是否存在自身定义的属性,不包含继承父类的属性

// 返回true,因为包含age属性
person.hasOwnProperty('age')
// 返回false,因为toString为父类属性,自身没有定义,当然如果重写toString,则会返回true
person.hasOwnProperty('toString')

对象的内置函数

valueOf()

对于基本数据类型,封装为对象后,调用该函数返回的是基本数据类型本身的数值。

对于其它对象,返回的是对象本身。但以下各种情况除外:

  • NaN:返回的还是NaN
  • null:调用该函数会报错;
  • undefined:调用该函数为报错;
toString()

对于基本数据类型,封装为对象后,调用该函数返回的是基本数据类型本身的数值。

对于其它对象,一般返回为:[Object, Object]。但以下几种情况除外:

  • NaN:返回的是NaN字符串,即:‘NaN’;
  • null:调用该函数会报错;
  • undefined:调用该函数为报错;

内置对象

Date

let date = new Date();

//获取日期的时间戳
console.log(date.getTime());;
//set新的时间戳来设置新的日期
date.setTime(11132132132);

//get 方法,返回的都是number类型
//年份
console.log(date.getFullYear());
//月份,注意:是从0开始的,因此实际月份需要加1,如:2020-11-23,则返回的月份为10
console.log(date.getMonth());
//日
console.log(date.getDay());
//小时
console.log(date.getHours());
//分钟
console.log(date.getMinutes());
//秒
console.log(date.getSeconds());
//毫秒
console.log(date.getMilliseconds());

//set 方法,与get对应

//to 转换方法,转为:2020/11/23 下午10:49:51
console.log(date.toLocaleString());
//返回:2020/11/23
console.log(date.toLocaleDateString());
//返回:下午10:49:51
console.log(date.toLocaleTimeString());
//...

JSON

//定义一个对象
let person = {
    name:`billy`,
    age:18,
    city: [2, 10, 24]
};

//将对象转成json字符串,JSON.stringify()方法可以传入任何参数
let personString = JSON.stringify(person);
console.log(personString);

//将Json字符串转成Json对象,JSON.parse()方法只能传入字符串参数
let personJson2 = JSON.parse(personString);
console.log(personJson2);

对象原型

可以设置一个对象的原型(父类)来指定该对象的原型(继承)。

object.__proto__ = newObject

let person = {
    name: 'human',
    sex: 1,
    run: function () {
        console.log('run...');
    }
};

let boy = {
    name: 'billy'
};

//设置一个对象的原型,也就是相当于设置一个对象的父类,设置后,就会继承父类的属性和方法
boy.__proto__ = person;
//设置原型后,即可访问原型中的方法和属性
boy.run();
boy.sex;

数组

length

返回数组长度。可以更改。

indexOf(a)

返回数组中指定下标对应的值。

slice(a,b)

截取数组的一部分内容生成一个新的数组。从下标a开始截取,共截取b-a个长度的值,类似于string对象的substring方法,包含下标a的内容,不包含下标b的内容。

push(a…)和pop()

  • push(a…):向数组的尾部压入新的内容(压栈),参数可以是多个,类似于list.add();
  • pop():返回数组尾部的一个对象,并从数组中移除该对象,类似于出栈;

unshift(a…)和shift()

  • unshift(a…):向数组的头部插入新的内容,参数可以是多个,类似于list.add(0, x);
  • shift():返回数组头部的一个对象,并从数组中移除该对象;

sort()

升序排序

reverse()

元素反转。如:[1,2,3,4,5]变成[5,4,3,2,1];

concat([…])

向数组中添加其它数组。类似于集合的addAll();

concat()没有修改原数组,而是返回的是一个新的数组。

join(‘-’)

将数组的每个item拼接在一起,每个item中间用指定的字符连接。

如:arr=[‘a’,‘b’,‘c’],则arr.join(’-’) = ‘a-b-c’

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值