new原理分析

首先先来段我们熟悉的代码

function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    console.log('i can speak');
}


let girl = new Person('weboof', 18);

console.log(girl.name);
console.log(girl.age);
girl.say();

这是我们经常看到并且常用的代码由此可以看出通过new创建出来的实例有以下几个特征:

  • new通过构造函数Person创造出来的实例可以访问构造函数中定义的属性和方法。
  • new通过构造函数Person创造出来的实例可以访问构造函数原型上的属性和方法。

接下来按照以上总结内容我们试着自己实现以下new操作符。首先我们需要了解以下几个问题点:

  • 如何让实例和构造函数产生关系如何实现属性和方法的继承?
  • 如何让实例和构造函数的原型产生关联?

简易版

function creat(Construction, ...args){
    let obj = {};
    Construction.call(obj, ...args);  //继承构造函数内部属性和方法
    //Construction.apply(obj, args);  //继承构造函数内部属性和方法
    Object.setPrototypeOf(obj, Construction.prototype); //连接原型
    return obj;
}


function Person(name, age) {
    this.name = name;
    this.age = age;
}
Person.prototype.say = function(){
    console.log('i can speak');
}


let girl = creat(Person, 'weboof', 18);

console.log(girl.name); //weboof
console.log(girl.age); //18
girl.say(); // i can speak

我们看到以上方法已经可以实现一个简易的new操作符了。接下来我们还需要讨论一下当构造函数有返回值时 会出现什么情况?

构造函数返回原始类型

function Person(name, age) {
    this.name = name;
    this.age = age;
    return 1
}
Person.prototype.say = function(){
    console.log('i can speak');
}


let girl = new Person('weboof', 18);

console.log(girl.name); //weboof
console.log(girl.age); //18
girl.say(); //i can speak

由此我们可以看出如果构造函数返回值为原始类型时对于创建出来的实例不会有任何影响。

构造函数返回对象类型

function Person(name, age) {
    this.name = name;
    this.age = age;
    return {
        name: 'hanhh'
    }
}
Person.prototype.say = function(){
    console.log('i can speak');
}


let girl = new Person('weboof', 18);

console.log(girl.name); //hanhh
console.log(girl.age); //undefined
girl.say(); //VM267:17 Uncaught TypeError: girl.say is not a function

由此可以看出如果构造函数返回的值为对象类型通过构造函数创建出的实例是会受到返回值的影响并且不会继承构造函数原型链上的属性和方法。

完整代码如下

function creat(con, ...args) {
  //con为传进来的构造函数
  let obj = {};
  //obj可以访问构造函数上面的属性和方法
  // let result = con.call(obj, ...args);
  let result = con.apply(obj, args);
  if(result instanceof Object) {
    return result;
  }else {
    Object.setPrototypeOf(obj, con.prototype); //obj可以访问构造函数原型链上的属性
    return obj;
  }
}

以上就是对new操作符的详细解释,希望对你有帮助~

 

Java词法分析器是Java编译器的一个重要组成部分,它的主要作用是将源代码转换为标记流(Token Stream),以便后续的语法分析器进行处理。Java词法分析器的原理如下: 1. 读取源代码:Java词法分析器首先读取源代码,并将其存储在内存中。 2. 分离标记:Java词法分析器将源代码分离成一个个标记(Token),每个标记代表一个关键字、标识符、运算符、分隔符或常量等。 3. 标记分类:Java词法分析器对每个标记进行分类,例如关键字、标识符、运算符、分隔符或常量等。 4. 标记属性:Java词法分析器为每个标记添加属性,例如标识符的名称、常量的值等。 5. 标记流:Java词法分析器将所有标记组成一个标记流(Token Stream),并将其传递给语法分析器进行处理。 以下是一个Java词法分析器的示例代码: ```java import java.io.*; import java.util.*; public class Lexer { private BufferedReader reader; private String line; private int lineNo; private int pos; public Lexer(String fileName) throws IOException { reader = new BufferedReader(new FileReader(fileName)); lineNo = 0; pos = 0; readLine(); } private void readLine() throws IOException { line = reader.readLine(); if (line != null) { lineNo++; pos = 0; } } private char peek() { if (line == null || pos >= line.length()) { return '\0'; } else { return line.charAt(pos); } } private char advance() throws IOException { char c = peek(); pos++; if (pos >= line.length()) { readLine(); } return c; } private boolean isWhitespace(char c) { return c == ' ' || c == '\t' || c == '\r' || c == '\n'; } private boolean isDigit(char c) { return c >= '0' && c <= '9'; } private boolean isLetter(char c) { return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'); } private String readIdentifier() throws IOException { StringBuilder sb = new StringBuilder(); char c = peek(); while (isLetter(c) || isDigit(c) || c == '_') { sb.append(advance()); c = peek(); } return sb.toString(); } private int readNumber() throws IOException { int value = 0; char c = peek(); while (isDigit(c)) { value = value * 10 + (c - '0'); advance(); c = peek(); } return value; } public Token nextToken() throws IOException { while (true) { char c = peek(); if (isWhitespace(c)) { advance(); } else if (isLetter(c)) { String identifier = readIdentifier(); return new Token(TokenType.IDENTIFIER, identifier); } else if (isDigit(c)) { int value = readNumber(); return new Token(TokenType.NUMBER, value); } else if (c == '+') { advance(); return new Token(TokenType.PLUS, "+"); } else if (c == '-') { advance(); return new Token(TokenType.MINUS, "-"); } else if (c == '*') { advance(); return new Token(TokenType.MULTIPLY, "*"); } else if (c == '/') { advance(); return new Token(TokenType.DIVIDE, "/"); } else if (c == '(') { advance(); return new Token(TokenType.LEFT_PAREN, "("); } else if (c == ')') { advance(); return new Token(TokenType.RIGHT_PAREN, ")"); } else if (c == '\0') { return new Token(TokenType.EOF, ""); } else { throw new RuntimeException("Invalid character: " + c); } } } } enum TokenType { IDENTIFIER, NUMBER, PLUS, MINUS, MULTIPLY, DIVIDE, LEFT_PAREN, RIGHT_PAREN, EOF } class Token { public TokenType type; public Object value; public Token(TokenType type, Object value) { this.type = type; this.value = value; } public String toString() { return String.format("(%s, %s)", type, value); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值