文章目录
1. == 和 ===区别
== 只是判断值是否一致,
=== 会判断数据类型和数据是否都一致.
var a = "123";
var b = 123;
console,log(a == b); // true
console.log(a === b); // false
2. a++ 和 ++a区别
//在js中
a++; // 翻译一下就是a = a + 1
++a; // 翻译一下就是a = a + 1
a--; // 翻译一下就是a = a - 1
--a; // 翻译一下就是a = a - 1
两句话,
1. 不论是a++还是++a. 目的都是让a自增1.
2.
a++这个表达式整体运算出来的结果是 a
++a这个表达式整体运算出来的结果是 a + 1
a = 10
b = a++
console.log(b) // 10
console.log(a) // 11
a = 10
b = ++a
console.log(b) // 11
console.log(a) // 11
//难度升级
a = 10
a = a++
console.log(a) // 10
a = 10
a = ++a
console.log(a) // 11
3. 创建js对象的三种方式
let a = {};
let b = new Object();
let c = Object.create(Object);
console.log(a);
console.log(b);
console.log(c);
/*
{}
{}
Function {}
*/
4. 原型与原型链相关
__proto__
:是实例对象指向原型对象的指针,隐式原型,是每个对象都会有的一个属性。
prototype:是构造函数的原型对象,显式原型,只有函数才会有。
即在 JavaScript 中,prototype 这个属性,是只有函数才拥有的;而__proto__
属性是只有对象才拥有的属性。
所以不存在 构造函数.__proto__
或者是 实例.prototype
4.1 prototype
JavaScript 中,当创建一个函数的时候,这个函数就会自动创建一个 prototype
属性,该属性指向的就是原型对象。既然这个属性指向了原型对象,那么他能不能使用原型中的属性和方法呢?
// 构造函数
function Me() {
this.uName = "binglv";
this.sayName = function () {
console.log(this.uName);
};
}
let m1 = new Me(); // 创建实例
console.log(m1.uName) // binglv;
m1.sayName(); // binglv
Me.prototype.sex = "男";
Me.prototype.saySex = function () {
console.log(this.sex);
}
console.log(m1.sex); // 男
m1.saySex(); // 男
每一个函数被创建的时候,会创建一个 prototype 属性,这个属性是一个对象,这个对象就是通过调用构造函数创建的对象的原型。
在原型对象上面定义的属性和方法可以被实例共享。不仅可以在构造函数中创建属性和方法,也可以将属性和方法直接赋值给他们的原型。
4.2 proto
每次调用构造函数创建的一个新实例,这个实例的内部有一个 [[Prototype]] 指针就会被赋值为构造函数的原型对象,因为 JavaScript 脚本中没有访问这个 [[Prototype]] 特性的标准方式,但是 Firefox、Safari 和 Chrome 会在每个对象上暴露__proto__
属性,通过这个属性可以访问对象的原型。
构造函数的 prototype
属性指向的是原型对象;实例的 __proto__
属性指向的是构造函数的原型对象。
验证:
// 构造函数
function Me() {
this.uName = "binglv";
this.sayName = function () {
console.log(this.uName);
};
}
let m1 = new Me(); // 创建实例
console.log(m1.__proto__ === Me.prototype); // true
4.3 constructor
既然构造函数可以通过 prototype 属性访问原型对象,那么原型对象可以通过什么手段来访问构造函数呢?
答案是肯定的。默认情况下,所有的原型对象自动获得一个名为 constructor 的属性,指回与之关联的构造函数。
// 构造函数
function Me() {
this.uName = "binglv";
this.sayName = function () {
console.log(this.uName);
};
}
console.log(Me.prototype); // 实例对象
console.log(Me.prototype.constructor === Me); // true
总结如下:
// 构造函数
function Me() {
this.uName = "binglv";
this.sayName = function () {
console.log(this.uName);
};
}
let m1 = new Me(); // 创建实例
// 如下条件为 true
console.log(Me === Me.prototype.constructor); // true
console.log(m1.__proto__ === Me.prototype); // true
// 从上面这一句可以推断出下面这个条件为 true
console.log(m1.__proto__.constructor === Me.prototype.constructor); // true
// 从上面三个语句中可以推断出下面的条件为 true
console.log(m1.__proto__.constructor === Me); // true
// 这里是上个知识点刚说明的
console.log(m1.constructor === Me); // true
// 根据上面两句可以得到:
console.log(m1.__proto__.constructor === m1.constructor); // true
两个结论:
1. m1.__proto__.constructor === Me
2. m1.__proto__.constructor === m1.constructor
4.4 原型链
原型链通俗易懂的理解就是可以把它想象成一个链条,互相连接构成一整串链子!
而原型链中就是实例对象和原型对象之间的链接。
每个函数都有一个prototype属性,这个prototype属性就是我们的原型对象,我们拿这个函数通过new构造函数创建出来的实例对象,这个实例对象自己会有一个指针(proto)指向他的构造函数的原型对象!这样构造函数和实例对象之间就通过( proto )连接在一起形成了一条链子。
为什么要使用原型链呢?
1.为了实现继承,简化代码,实现代码重用!
2.只要是这个链条上的内容,都可以被访问和使用到!
使用原型链有什么作用?
1. 继承
2. prototype用来实现基于原型的继承与属性的共享
3. 避免了代码冗余,公用的属性和方法,可以放到原型对象中,这样,通过该构造函数实例化的所有对象都可以使用该对象的构造函数中的属性和方法!
4. 减少了内存占用
原型链的特点:
1. 就近原则,当我们要使用一个值时,程序会优先查找离自己最近的,也就是本身有没有,如果自己没有,他就会沿着原型链向上查找,如果还没有找到,它还会沿着原型链继续向上查找,直到到达Object
2. 引用类型,当我们使用或者修改原型链上的值时,其实使用的是同一个值!
3. JS中每个函数都存在原型对象属性prototype。并且所有函数的默认原型都是Object的实例。
4. 每个继承父函数的实例对象都包含一个内部属性_proto_。该属性包含一个指针,指向父函数的prototype。若父函数的原型对象的_proto_属性为再上一层函数。在此过程中就形成了原型链。
// 原型链
// 1.原型 -> 类
// 2.原型对象 -> 类中属性与方法组成的一个对象
// 3.实例对象 -> 创建的实例
// 4.如何互相转换
// 原型(它是一个函数)
function User(){
}
console.log("原型:",User);
User.prototype.username = "test";
User.prototype.password = "123456";
User.prototype.login = function login(username, password){
console.log(`${username}登录成功`);
}
// 从原型到原型对象
console.log("原型对象:",User.prototype);
// 从原型到实例对象
let user = new User();
console.log(user);
user.login("小明", "1");
// 从原型对象到原型
console.log(User.prototype.constructor === User);
// 从原型对象到实例对象
let user2 = new User.prototype.constructor();
console.log(user2);
// 从实例对象到原型对象
console.log(user.__proto__ === User.prototype);
console.log(Object.getPrototypeOf(user) === User.prototype);
// 从实例对象到原型
console.log(user.__proto__.constructor === User);
console.log(Object.getPrototypeOf(user).constructor === User);
/*
原型: [Function: User]
原型对象: { username: 'test', password: '123456', login: [Function: login] }
User {}
小明登录成功
true
User {}
true
true
true
true
*/
5. 定时器的两种设置方式
// 语法规则
t = setTimeout(函数, 时间)
// 经过xxx时间后, 执行xxx函数
// 5秒后打印我爱你
t = setTimeout(function(){
console.log("我爱你")
}, 5);
window.clearTimeout(t) // 停止一个定时器
//语法规则
t = setInterval(函数, 时间)
// 每隔 xxx时间, 执行一次xxx函数
// 每隔5秒钟, 打印`我爱你`
t = setInterval(function(){
console.log("我爱你")
}, 5000)
window.clearInterval(t) // 停止一个定时器
for(let i = 0; i <= 9999; i++)window.clearInterval(i); // 清理掉所有定时器
6. 时间相关
var d = new Date(); // 获取系统时间
console.log(d) // 2023-08-02T06:19:10.470Z
// var d = new Date("2023-08-01 06:19:10"); // 得到一个具体时间
// console.log(d)
// d.getTime() // 时间戳. 表示从1970-1-1 00:00:00 到现在一共经过了多少毫秒
// 时间格式化
year = d.getFullYear(); // 拿到年份
month = d.getMonth() + 1; // 拿到月份. 注意月份从0开始
date = d.getDate(); // 拿到日期
hour = d.getHours(); // 拿到小时
minute = d.getMinutes(); // 分钟
seconds = d.getSeconds(); //秒
format_date = year + "-" + month + "-" + date + " " + hour + ":" + minute + ":" + seconds;
console.log(format_date)
7. axios与axios拦截器
由于jquery有严重的地狱回调逻辑. 再加上jquery的性能逐年跟不上市场节奏. 很多前端工程师采用axios来发送ajax. 相比jquery. axios更加灵活. 且容易使用. 更加美丽的是. 这玩意是用promise搞的. 所以更加贴合大前端的项目需求. 来吧. 上手试试吧
<script src="/static/axios.min.js"></script>
<script>
window.onload = function(){
axios.post("/movies", {"page": 10086}).then(function(resp){
console.log(resp.data);
})
}
</script>
看到没. 这玩意比jquery简单n多倍. 而且, axios为了更加适应大前端. 它默认发送和接收的数据就是json. 所以, 我们在浏览器抓包时.
直接就是request payload. 这对于前端工程师而言. 爽爆了.
在前端, 我们能看到有些网站会对每次请求都添加加密信息. 或者每次返回数据的时候, 都有解密逻辑. 那此时. 你思考.不可能每次请求都要程序员去手动写加密逻辑. 例如:
window.onload = function(){
// 加密数据
axios.post("/movies", {"page": 10086}).then(function(resp){
明文 = 解密(resp.data);
console.log(明文);
})
// 加密数据
axios.post("/movies", {"page": 10086}).then(function(resp){
明文 = 解密(resp.data);
console.log(明文);
})
}
这样很麻烦. 也很蛋疼. axios想到过类似的问题. 它提供了拦截器. 一次性处理好这种问题
axios.interceptors.request.use(function(config){ // 拦截所有请求
console.log("我是拦截器. 我可以对数据进行加密");
console.log(config)
return config;
}, function(error){
return Promise.reject(error);
});
axios.interceptors.response.use(function(response){ // 拦截所有响应
console.log("我是响应回来之后拦截器. 我可以对数据进行解密")
return response.data;
}, function(error){
return Promise.reject(error);
});
这样. 对于业务层的代码而言就简单很多了
window.onload = function(){
// 加密的逻辑拦截器帮我完成了
axios.post("/movies", {"page": 10086}).then(function(data){
// 解密的逻辑拦截器帮我完成了
console.log(data);
})
// 加密的逻辑拦截器帮我完成了
axios.post("/movies", {"page": 10086}).then(function(data){
// 解密的逻辑拦截器帮我完成了
console.log(data);
})
}