百度前端课学习笔记2:JS 基础1

379 阅读5分钟

内容全部整理自 西安电子科技大学 2020双创周的百度前端课程,感谢组织课程的百度技术学院。

感谢百度的工程师柳老师的讲解,内容非常精彩,此为课程链接: mbd.baidu.com/webpage?typ…

该笔记基本按课程顺序记录,由于时间精力紧张,不会对本文进行全面的结构及内容整理 插图全部来自课堂直播画面

太过基础的东西会直接略过,只记录我个人觉得有必要提一下的东西

js 中的表达式都是有返回值的,但语句没有返回值

类型相关

  • js 中只有浮点数

  • null,通常是想强调说“这里本应由一个对象,但还不存在”

  • 字符串和其它类型相加,都会转为字符串

  • 使用加号加一个不能被转换为数字的字符串,会返回【NaN】(Not a Number)

  • js中不建议使用双等号而是三等号,原因是很多双等号的返回值反常识,具体见下图

变量相关

  • 建议使用 let、const 进行变量定义

  • 声明后的变量都可以随便转换类型

  • 判断变量类型可用 console.log(typeof a)

  • const 的值不能修改

    const b = 1;
    b = 2; 		// 错误
    
  • js 中同一个数组中各个元素的类型可以是任意的

  • 例:输出目录树

函数相关

写法和参数

function add(a, b) {
    return a+b;			// 若没有返回值,则会返回 undefined
}

实际传参,可以传入的比函数要的多,也可以比函数要的少。如果少了,没传的就是 undefined

对于传参不足的情况,我们可以通过在函数内检查参数,或者通过指定默认值来防止出错

function add(a, b) {
    if(typeof b === 'undefined') {
        b=0;
    }
    if(typeof a === 'undefined') {
        a=0;
    }
    // ...
}

// 也可以指定默认值
function add(a = 0, b = 0) {
    // ...
}

定义提升

其实就是可以在定义函数之前对函数进行调用,解释器会找出来定义的函数然后把它提到调用之前(实际上,是整个代码文件的最头部),这样就不会报错了

使用表达式定义函数

这种定义方式不会有定义提升

const minius1 = function minus2(a, b) {
	return a-b;
};

const minius3 = function (a, b) {		// 实际上可以直接把名字去掉
	return a-b;
};

箭头函数

const minius4 = (a, b) => {
	return a-b;
}

const minius5 = (a, b) => a-b;	// 更加简洁的写法

const returnSelf = x => x;		// 只有一个参数的情况,可以省略参数括号

函数也作为参数传递给其他函数

函数作为返回值(生成函数的函数)

const buildRepeatChar = char => {
	return num => {					// 该函数的返回值是一个函数
        let res = '';
        while(num--) {
            res += char;
        }
        return res;
    }
}

下面这张图中体现了闭包,值得多看看。。

可以注意到,repeatBar 在这里其实是一个对象,其包含了【返回函数的函数】的“成员变量” count,这个【返回函数的函数】已经不再是执行结束就就结束生命周期被彻底销毁的东西,而是会作为一个变量一直存在下去。

另一个值得多看看的例子

下面的 sumBy([...], buildClamp(0, 3))的作用,其实是构造了一个上限为3下限为0的函数,这个函数的上线就是3而下限就是0,这个函数已经作为返回值成为了iteratee的值。

然后 sumBy 函数中直接调它,就相当于把这玩意的参数直接传给了buildClamp这个函数 return 的那个匿名函数

打印出来的结果是7

对象

对象,是属性的集合。属性就是一个 kv 对

// 定义一个对象
let folder1 = {
    'size': 2000,
    'other object': null,
    'subFiles': ['index.js'],
    log:()=>{		// 函数也可以作为对象的值,调用:folder1.log();
        console.log('func as value');
    }
};

// 属性名一定是字符串,所以是可以省略的,写成下面这样
let folder2 = {
    size: 2000,
    subFiles: ['index.js'],
    'other object': folder1	// 有空格的需要引号.属性值可以是另一个对象
};

// 两种访问方式,可以用点,也可以用 key,也可以用能返回字符串的表达式
console.log(folder2.size, folder2['other object'], folder2['na'+'me'])

// 获取对象中所有的 key ,下面的 Object 是一个全局对象
console.log(Object.keys(student));
// 访问对象的方法 for in:
for(const key in student) {	// 变量 key 标识 student 的每个属性名
    						// 【对 student 中的每个属性 key...】
    console.log(key, student[key])
}

// 检查对象是否包含某个属性(使用 in):
console.log('classmate' in student, 'teacher' in student);
// 这个 in,如果属性在对象中就返回 true,反之 false

// 删除属性
delete student.teacher;

// 对象的引用
// 把一个对象赋值给一个变量,称为【这个变量指向这个对象所在的内存】
// 我们说“使用了 const 声明的变量不可变”,指的是【它指向一个特定的内存空间】这件事不会变,但对应的对象的内容当然还是可以改的。也就是说,const 导致引用不可变,但对象的属性可变

class

class Rectangle {
    constructor(length, width) {
        this.length = length;		// this 指向的是当前的对象自身
        this.width = width;
    }
    area() {
        return this.length * this.width;
    }
}

const rect = new Rectangle(20, 10);	// 实例化,记得写 new

对于任意一个对象的类,其都会有一个基类。这个最基的基类叫做“Object”。

数组

数组也是个对象

const arr1 = new Array(3);
const arr2 = [10, 20, 30];	// 两种写法一致

arr2.push(22);	// 增加
arr2.slice(1, 3);	// 返回这一段

基本类型的包装对象

使用基本类型(Number、String、Boolean)都会被 js 自动包装成一个对象(包装自动进行)

console.log('1234'.length);		// 因此可以这么写
console.log('1,2,3,4'.split(','));	// 也可以这么写

console.log((2).toFixed(3));		// 数字的话不能直接加.,要包一下

其他内置对象

Date:时间相关

const date = new Date();
const hour = date.getHours();
const minues = date.getMinutes();
const second = date.getSeconds();
// 例子就上面这样

setInterval(()=>{
    document.body.innerHTML = '...';		// 重新获取下时间更新上去
}, 1000);		// 每隔 1000ms 调用一次花括号里面的函数

Math:数学相关

JSON:可用于序列化