感兴趣的朋友可以去我的语雀平台进行查看更多的知识。
https://www.yuque.com/ambition-bcpii/muziteng
JavaScript使用专门的关键字let和var来声明(定义)变量,在使用时需要注意一些细节
let注意事项
Uncaught ReferenceError错误JavaScript中内置的一些关键字不能被当做变量名var注意事项
大部分情况使用let和var区别不大,但是let相较var更严谨,因此推荐使用let
特点
js是弱类型动态语言,只有程序运行过程中才能确定类型JavaScript中变量的值决定了变量的数据类型。数据类型的分类
| 简单数据类型 | 说明 | 默认值 |
|---|---|---|
| Number | 数字型,整数或浮点数 | 0 |
| Boolean | 布尔值true false | false |
| String | 字符串 | “” |
| Undefined | 变量只实名还没有赋值 | undefined |
| Null | 空值 | null |
| bigint | 是一种数字类型的数据,它可以表示任意精度格式的整数 | |
| symbol |
数字型:即我们数学中学习到的数字,可以是整数、小数、正数、负数
最大值Number.MAX_VALUE,比最大值大就是无穷大Infinty
最小值 Number.MIN_VALUE,比最小值小就是无穷大-Infinty
非数字 NaN isNaN()判断是否非数字
undefined和数字相加最后的结果是NaN
转换为字符串

转换为数字型(重点)

转换为布尔型

instanceof(判断实例方法)
instanceof 运算符用于检测构造函数的prototype属性是否出现在某个实例对象的原型链上var b1 = {
b2: [1, 'abc', console.log],
//可以简化成 b3:()=>()=> 'hongjilin' -->高阶函数相关知识
b3: function () {
return () =>{ return 'hongjilin'}
}
}
/**使用instanceof进行对象判断*/
console.log(b1 instanceof Object, b1 instanceof Array) // true false
console.log(b1.b2 instanceof Array, b1.b2 instanceof Object) // true true
console.log(b1.b3 instanceof Function, b1.b3 instanceof Object) // true true
/**使用typeof进行对象中某属性的判断*/
console.log(typeof b1.b2, typeof null) // 'object' 'object'
console.log(typeof b1.b3='function') // true
console.log(typeof b1.b2[2]='function') //true
/**调用对象与数组中某函数示例*/
b1.b2[2]('调用console.log打印hongjilin') //调用console.log打印hongjilin
console.log(b1.b3()()) // hongjilin
函数形参和实参个数不匹配问题

arguments实际上它是当前函数的一个内置对象。所有函数都内置了一个arguments对象,arguments对象中存储了传递的所有实参。
只要是代码,就至少有一个作用域,写在函数内部的局部作用域,如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域
根据在内部函数可以访问外部函数变量的这种机制,用链式查找决定哪些数据能被内部函数访问,就称作用域链,作用域链就是采取就近
原则的方式来查找变量最终的值。
function f1() {
var num = 123;
function f2() {
console.log( num );
}
f2();
}
var num = 456;
f1();

JavaScript中的对象分为3种
ECMAScriptECMAScriptJS独有的内置对象:指JS语言自带的一些对象,供开发者使用,提供了一些常用的最基本而必要的功能(属性和方法)
JavaScript提供了多个内置对象:Math、 Date 、Array、String等文档:MDN
Math.PI // 圆周率
Math.floor() // 向下取整
Math.ceil() // 向上取整
Math.round() // 四舍五入版 就近取整 注意 -3.5 结果是 -3
Math.abs() // 绝对值
Math.max()
Math.min() // 求最大和最小值
Math.random() // 随机数方法,返回一个随机的小数 0 =< x < 1
Date实例用来处理日期和时间。
Date对象和Math对象不一样,他是一个构造函数,所以我们需要实例化后才能使用
let date = new Date();
console.log(date); // Sun Sep 11 2022 19:17:01 GMT+0800 (中国标准时间)

获取日期的总的毫秒形式
Date对象是基于1970年1月1日(世界标准时间)起的毫秒数,常利用总的毫秒数来计算时间,因为它更精确
valueOf() getTime() new Date() Date.now()获得距离1970年1月1号过了多少毫秒数
数组对象的创建
字面量方式 []
new Array([length]) new Array(...元素)
检测是否为数组
instanceof运算符,可以判断一个对象是否属于某种类型Array.isArray() 用于判断一个对象是否为数组,isArray()是HTML5中提供的方法添加删除数组元素的方法


注意:sort()默认按照比较字符串大小的方式一个字符一个字符的比,数字也是,除非传入一个方法



slice(start, end)
start可以为负数,表示从数组尾部开始算起的位置。-1指最后一个元素,-2指倒数第二个元素,以此类推end如果没有被指定,表示到最后。若指定,表示左闭右开 [start,end)splice(start[, deleteCount[, item1[, item2[, ...]]]])
start表示从什么位置开始添加或删除数组元素deleteCount表示删除的元素数量,如果为0,则表示不删除数组元素item1[, item2[, ...]]]] 表示新增的数组元素let arr1 = [13, 4, 77, 1, 7];
arr1.sort((a, b) => a - b); // 升序
console.log(arr1)
arr1.sort((a, b) => b - a); // 降序
console.log(arr1)
console.log(arr1.join()) // 默认为,
let numbers = arr1.slice(1, 4); // 4,77,1 [begin,end) 左闭右开
console.log(numbers)
arr1.splice(1, 3); // [13,7]
console.log(arr1)
字符串的不可变
指的是里面的值不可变,虽然看上去可以改变内容,但其实是地址变了,内存中新开辟了一个内存空间。



replace(被替换的字符串, 替换为的字符串) 用于在字符串中用一些字符替换另一些字符,只替换第一个
split()用于切分字符串,它可以将字符串切分为数组。在切分完毕之后,返回的是一个新数组。
toUpperCase()转换大写
toLowerCase()转换小写
includes()方法用于判断一个字符串是否包含在另一个字符串中,根据情况返回 true 或 false
常见的回调函数
dom事件回调函数 ==> 发生事件的dom元素ajax请求回调函数// dom事件回调函数
document.getElementById("btn").onclick = function () {
alert(this.innerHTML);
}
// 定时器回调函数
setTimeout(function () {
alert("到点了" + this)
}, 2000);
this
如何确定this的值?
function Person(color) {
console.log(this);
this.color = color;
this.getColor = function () {
console.log(this)
return this.color;
}
this.setColor = function (color) {
console.log(this)
this.color = color;
}
}
const obj = {};
Person("red"); //this是谁? window
const p = new Person("yello"); //this是谁?p
p.getColor();
// 调用call会改变this指向--->让我的p函数称为obj的临时方法及逆行调用
p.setColor.call(obj, "black"); //this是谁?obj
const test = p.setColor;
test(); //this是谁?window
函数的prototype属性
每个函数都有一个prototype属性,它默认指向一个Object空对象(即称为原型对象)
原型对象中有一个属性constructor,它指向函数对象

给原型对象添加属性(一般都是方法)
// 每个函数都有一个prototype属性,它默认指向一个Object空对象(原型对象)
console.log(Date.prototype, typeof Date.prototype);
function Fun() {
}
console.log(Fun.prototype) // 默认指向一个Object空对象(没有自己的属性)
// 原型对象中有一个属性constructor,它指向函数对象
console.log(Date.prototype.constructor === Date) // true
console.log(Fun.prototype.constructor === Fun) // true
// 给原型对象添加属性、方法(一般是方法) ===> 实例对象可以访问
Fun.prototype.test = function () {
console.log("test()")
}
let fun = new Fun();
fun.test();

function都有一个prototype,即显式原型属性__proto__,可称为隐式原型属性// 定义构造函数
function Fn() {
// 内部默认执行语句:this.prototype = {}
}
// 1.每个函数function都有一个prototype,即显示原型属性,默认指向一个空的Object对象
console.log(Fn.prototype)
// 创建实例对象
let fn = new Fn() // 内部默认执行语句:this.__proto__ = Fn.prototype
// 2.每个实例对象都有一个__proto__,可称为隐式原型
console.log(fn.__proto__)
// 3.对象的隐式原型的值为其对应构造函数的显示原型的值
console.log(Fn.prototype === fn.__proto__) // true
// 给原型添加方法
Fn.prototype.test = function () {
console.log("test()")
}
// 通过实例对象调用原型方法
fn.test(); // test()
内存结构

总结
函数的prototype属性:在定义函数时自动添加的,默认值是一个空Object实例对象(Object 函数除外,因为__proto__ 属性为
null)
对象的__proto__ 属性:创建对象时自动添加的,默认值为构造函数的prototype属性值,Function函数
程序员可以直接操作显式原型,但不能直接操作隐式原型(ES6之前)
原型链
访问一个对象的属性时
__proto__这条链向上查找,找到返回undefined
构造函数/原型/实例对象的关系(图解)
var o1 = new Object();
var o2 = {};

所有函数的__proto__都是一样的
Function函数的实例,包括Function本身Object的原型对象是原型链的尽头Object.prototype.__proto__为 null
属性问题
读取对象的属性值时:会自动到原型链中查找
设置对象的属性值时:不会查找原型链,如果当前对象中没有此属性,直接添加此属性并设置其值
方法一般定义在原型中,属性一般通过构造函数定义在对象本身上
返回函数的函数[高阶函数]
let val = 7
function createAdder() {
function addNumbers(a, b) {
let ret = a + b
return ret
}
return addNumbers
}
let adder = createAdder()
let sum = adder(val, 8)
console.log('example of function returning a function: ', sum)
高阶函数:就是一个函数就可以接收另一个函数作为参数,或者是返回一个函数–>常见的高阶函数有map、reduce、filter、sort等
let add = function add(a) {
return function (b) {
return a + b;
}
}
console.log(add(2)(3)); //5
map
// map接受一个函数作为参数,不改变原来的数组,返回一个全新的数组
let arr = [1, 2, 3, 4, 5];
let arr2 = arr.map(item => item * 2);
console.log(arr2) // [2,4,6,8,10]
reduce
let arr = [1, 2, 3, 4, 5];
// reduce接受一个函数作为参数,这个函数要有两个形参,代表数组中的前两项
// reduce会将这个函数的结果与数组中的第三项再次组成这个函数的两个形参以此类推进行累计操作
let arr3 = arr.reduce((a, b) => a + b);
console.log(arr3); // 15
filter
let arr = [1, 2, 3, 4, 5];
// filter返回过滤后的数组。filter也接受一个函数作为参数,这个函数作用于数组中的每个元素
// 根据该函数每次执行后返回的布尔值来保留结果,如果是true就保留,如果是false就过滤掉
let arr4 = arr.filter(item => item % 2 === 0);
console.log(arr4); // [2,4]
…TODO
// 父类型
function Supper() {
this.supProp = '父亲的原型链'
}
// 给父类型的原型上增加一个 showSupperProp 方法,打印自身 subProp
Supper.prototype.showSupperProp = function () {
console.log(this.supProp)
}
// 子类型
function Sub() {
this.subProp = '儿子的原型链'
}
// 子类型的原型为父类型的一个实例对象
Sub.prototype = new Supper()
// 让子类型的原型的constructor指向子类型
// 如果不加,其构造函数找的[`new Supper()`]时从顶层Object继承来的构造函数,指向[`Supper()`]
Sub.prototype.constructor = Sub
// 给子类型的原型上增加一个 showSubProp 方法,打印自身 subProp
Sub.prototype.showSubProp = function () {
console.log(this.subProp)
}
var sub = new Sub()
sub.showSupperProp() // 父亲的原型链
sub.showSubProp() // 儿子的原型链
console.log(sub)
/**
Sub {subProp: "儿子的原型链"}
subProp: "儿子的原型链"
__proto__: Supper
constructor: ƒ Sub()
showSubProp: ƒ ()
supProp: "父亲的原型链"
__proto__: Object
*/
示例图
注意:此图中没有体现 constructor 构造函数,会在下方构造函数补充处指出

Sub.prototype.constructor = Sub 如果不加,会指向 Supper
套路
关键
作用
function Person(name, age) {
this.name = name
this.age = age
}
function Student(name, age, price) {
// 此处利用call(),将 [Student]的this传递给Person构造函数
Person.call(this, name, age) // 相当于: this.Person(name, age)
/*this.name = name
this.age = age*/
this.price = price
}
var s = new Student('Tom', 20, 14000)
console.log(s.name, s.age, s.price)
Person中的this是动态变化的,在[Student]中利用[Person.call(this, name, age)]改变了其this指向,所以可以实现此效果
原型链 + 借用构造函数的组合继承
super()借用父类型构建函数初始化相同属性function Person(name, age) {
this.name = name
this.age = age
}
Person.prototype.setName = function (name) {
this.name = name
}
function Student(name, age, price) {
Person.call(this, name, age) // 为了得到属性
this.price = price
}
Student.prototype = new Person() // 为了能看到父类型的方法
Student.prototype.constructor = Student // 修正constructor属性
Student.prototype.setPrice = function (price) {
this.price = price
}
var s = new Student('Tom', 24, 15000)
s.setName('Bob')
s.setPrice(16000)
console.log(s.name, s.age, s.price)