谈谈你对原型的理解
查看详情
在 JavaScript 中,原型(prototype)是实现对象继承和共享属性的基础机制。通过原型,JavaScript 对象可以继承其他对象的属性和方法,从而实现代码的复用和对象的扩展。
原型链解决的是什么问题?什么是原型链?
查看详情
- 原型链解决的主要是继承问题
- 当谈到继承时,JavaScript 只有一种结构:对象。每个实例对象( object )都有一个私有属性(称之为
__proto__
)指向它的构造函数的原型对象(prototype)。该原型对象也有一个自己的原型对象(__proto__
) ,层层向上直到一个对象的原型对象为 null。
prototype 和__proto__
区别是什么?
查看详情
- prototype 是构造函数的属性
__proto__
是每个实例都有的属性- 实例的
__proto__
与其构造函数的 prototype 指向的是同一个对象
ES5 继承的方法有哪些?
查看详情
- 组合继承
javascript
function SuperType(name) {
this.name = name;
this.colors = ['red', 'green', 'blue'];
}
SuperType.prototype.sayName = function () {
console.log(this.name);
};
function SubType(name, age) {
SuperType.call(this, name);
this.age = age;
}
SubType.prototype = new SuperType();
SubType.prototype.constructor = SubType;
SubType.prototype.sayAge = function () {
console.log(this.age);
};
ES5/ES6 的继承的区别
查看详情
- 写法不同
- ES5
- ES6 通过 extends 关键字继承父类
- ES6 子类可以通过
__proto__
寻找到父类,而 ES5 函数通过__proto__
找到的是Function.prototype
javascript
class Super {}
class Sub extends Super {}
Sub.__proto__ === Super;
function Super() {}
function Sub() {}
Sub.prototype = new Super();
Sub.prototype.constructor = Sub;
Sub.__proto__ === Function.prototype;
this
生成的顺序不同- ES5 的继承先生成子类的实例,在调用父类的构造函数修饰子类实例
- ES6 的继承先生成父类实例,再调用子类的构造函数修饰父类的实例,这个差别使得 ES6 可以继承内置对象
ES6 继承的时候父类的哪些东西能否继承
查看详情
- 实例属性和方法:通过 super() 调用父类构造函数继承。
- 静态属性和方法:通过 extends 关键字继承。
- 访问器(getters 和 setters):可以直接继承父类定义的访问器方法。
- Symbol 属性:子类可以继承父类定义的 Symbol 属性和方法。
- 父类的构造函数:子类必须调用 super() 来调用父类的构造函数。
谈谈 JS 执行上下文栈和作用域链的理解
查看详情
- 执行上下文就是 JavaScript 代码被解析和执行时所在环境
- JavaScript 执行在单线程上,所有的代码都是排队执行,代码运行时创建的所有执行上下文被存储在执行栈(调用栈),遵循后进先出的规则
- 执行上下文有三种:
- 全局执行上下文:这是一个基础的上下文,任何不在函数内部的代码都会在全局上下文中。一个程序只有一个全局上下文,浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部,在关闭浏览器的时候出栈
- 函数执行上下文:当函数被调用的时候,会为函数创建一个新的上下文环境,并且把它压入执行栈的顶部。当函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收机制回收
- eval 函数执行上下文
- 作用域链:在使用变量的时候会从当前的作用域开始查找,如果没有找到,就会向上级作用域继续查找,每次上升一个作用域,一直找到全局作用域为止
new 的原理是什么?通过 new 的方式创建对象和通过字面量创建对象有什么区别?
查看详情
- 原理
- 创建一个空的简单 JavaScript 对象(即{})
- 将函数的 prototype 赋值给对象的
__proto__
属性 - 调用函数,并将步骤 1 新创建的对象作为函数的 this 上下文
- 如果该函数没有返回值或者返回值不是对象,则返回创建的对象,如果返回值是对象,则直接返回该对象。
javascript
function _new() {
let target = {};
let [constructor, ...args] = [...arguments];
target.__proto__ = constructor.prototype;
let result = constructor.apply(target, args);
if (result && (typeof result === 'object' || typeof result === 'function')) {
return result;
}
return target;
}
- 区别
- 字面量创建对象不会调用 Object 构造函数,简洁且性能更好
- new Object()方法创建对象本质上是方法调用,涉及到在 proto 联众遍历该方法,当找到该方法后,又会生产方法调用必须的堆栈信息,方法调用结束后,还要释放该堆栈,性能不如字面量的方式。