函数声明存在变量提升,会被提升到作用域最前面。
函数表达式,不会被提升,仍然按照从上往下读取。
函数的4种类型:函数声明、箭头函数、函数表达式、函数对象
// 1️⃣:函数声明
async function fn() {
await f()
}
// 2️⃣:函数表达式
const fn = async function () {
await f()
};
// 3️⃣:箭头函数
const fn = async () => {
await f()
};
// 4️⃣:async函数定义在对象中
const obj = {
async fn() {
await f()
}
}
参考阅读: 深入理解JavaScript5:强大的原型和原型链
当我们访问一个对象的属性时,如果这个对象内部不存在这个属性,那么它就会去它的原型对象里找这个属性,这个原型对象又会有自己的原型,于是就这样一直找下去,也就是原型链的概念。原型链的尽头一般来说都是 Object.prototype 所以这就是我们新建的对象为什么能够使用 toString() 等方法的原因。

this ,函数执行的上下文,可以通过 apply , call , bind 改变 this 的指向。对于匿名函数或者直接调用的函数来说,this指向全局上下文(浏览 器为window,NodeJS为 global ),剩下的函数调用,那就是谁调用它, this 就指向谁。当然还有es6的箭头函数,箭头函数的指向取决于该箭头函 数声明的位置,在哪里声明, this 就指向哪里。
推荐阅读:深入理解JavaScript系列:变量对象Variable Object
当执行 JS 代码时,会生成执行环境,只要代码不是写在函数中的,就是在全局执行环境中,函数中的代码会产生函数执行环境。在生成执行环境时,会有两个阶段。第一个阶段是创建的阶段,JS 解释器会找出需要提升的变量和函数,并且给他们提前在内存中开辟好空间,函数的话会将整个函数存入内存中,变量只声明并且赋值为 undefined ,所以在第二个阶段,也就是代码执行阶段,我们可以直接提前使用
原型链继承、借用构造函数继承、组合继承(组合原型链继承和借用构造函数继承)(常用)、原型式继承、寄生组合式继承(常用)
推荐阅读:JS继承的6种方式
/* create函数要接受不定量的参数,第一个参数是构造函数(也就是new操作符的目标函数),
其余参数被构造函数使用。
new Create() 是一种js语法糖。我们可以用函数调用的方式模拟实现 */
function create(Con,...args){
//1、创建一个空的对象
let obj = {}; // let obj = Object.create({});
//2、将空对象的原型prototype指向构造函数的原型
Object.setPrototypeOf(obj,Con.prototype); // obj.__proto__ = Con.prototype
//3、改变构造函数的上下文(this),并将剩余的参数传入
let result = Con.apply(obj,args);
//4、在构造函数有返回值的情况进行判断
return result instanceof Object?result:obj;}
这里需要注意对构造函数返回值的判断
在new的时候,会对构造函数的返回值做一些判断:
1、如果返回值是基础数据类型,则忽略返回值;
2、如果返回值是引用数据类型,则使用return 的返回,也就是new操作符无效
推荐阅读:深入理解JavaScript系列:闭包(Closures)
function format(number) {
return number && number.replace(/(?!^)(?=(\d{3})+\.)/g, ",");
}

对象所独有的;函数所独有的,因为函数也是一种对象,所以函数也拥有__proto__和constructor属性。对象的属性时,如果该对象内部不存在这个属性,那么就会去它的__proto__属性所指向的那个对象(父对象)里找,一直找,直到__proto__属性的终点null,然后返回undefined,再往上找就相当于在null上取值,会报错。通过__proto__属性将对象连接起来的这条链路即我们所谓的原型链。/** moduleA.ts */
export default function testA() {
console.log('this is A');
const name = 'testA';
return name;
}
/** moduleB.ts */
export default function testB() {
const name = 'testB';
console.log('this is B');
return name;
}
/**main.vue*/
import testA from './moduleA';
onMounted(() => {
testA();
// 动态引入moduleB
import('./moduleB').then(module => {
module.default();
console.log('log内容testb', module.default.name);
});
console.log('log内容testA', testA.name);
});
/**输出
this is A
log内容testA testA
this is B
log内容testb testB
*/