1、 手写new的实现过程
主要实现步骤:
- 生成一个新对象
- 为这个对象设置prototype
- 使用this执行构造函数
- 返回这个对象
function _new() {
// 1.生成一个新对象
let obj= {};
// 第一个参数是构造函数
let [Fn, ...args] = [...arguments];
// 2.为这个对象设置prototype;实际上就是生产了一个新的上下文
obj.__proto__ = Fn.prototype;
// 3.使用apply在obj作用域中调用构造器函数,属性和方法被添加到 this 引用的对象即obj中
let result = Fn.apply(obj, args);
if (result && (typeof (result) == "object" || typeof (result) == "function")) {
// 如果构造函数执行的结果返回的是一个对象,那么返回这个对象
return result;
}
// 4.如果构造函数返回的不是一个对象,返回创建的新对象
return obj;
}
var person1=_new(Person, 20) // 相当于 var person1 = new Person(20);
2、es5和es6中类的对比
静态、私有变量等, 定义实现的对比
es5
function Point(){
// 私有变量
var num = 10;
// 定义获取私有变量的方法 在原型上不能直接获取私有变量
this.getNum = function(){
return num;
}
// public
this.x = x; //x,y定义在对象自身上面
this.y = y;
}
Point.prototype.add = function(){
console.log(this.x + this.y);
console.log(this.getNum()); // 获取私有变量 这里this.num直接获取不了 使用闭包返回数据
}
//静态属性
Person.total = 0;
//静态方法
Point.counter = function(){
return 'staticFn';
}
var p = new Point(2, 3);
p.add(); //输出5 1 0
es6
class Point{
constructor(x, y) { //相当于java中的构造函数,如果不写默认为空
// public
this.x = x; //x,y定义在对象自身上面
this.y = y;
}
// 私有属性 es2020
#num = 10;
//静态属性
static total = 0;
//静态方法
static counter(){
return 'staticFn';
}
add() { //该方法定义在Point.prototype上
console.log(this.x + this.y);
// 访问私有属性
console.log(this.#num);
}
}
var p = new Point(2, 3);
p.add(); //输出5 10
3、ES6中当函数用new关键词的时候,增加了new.target属性来判断当前调用的构造函数
1、可以限制函数的调用,比如一定要用new命令来调用
function Person(name){
if(new.target === Person){
this.name = name;
}
else{
throw new Error('必须用new生成实例');
}
}
2、限制类的调用方法,判断new.target是不是未定义。写出只能被继承使用的类。
class Shape {
constructor() {
if (new.target === Shape) {
throw new Error('本类不能实例化');
}
}
}
class Rectangle extends Shape {
constructor(length, width) {
super();
// ...
}
}
var x = new Shape(); // 报错
var y = new Rectangle(3, 4); // 正确