JavaScript学习代码

57 阅读1分钟

1.new实现的过程

function newFun(Fun, ...args) {
  // 1.先创建一个空对象
  let newObj = {};
  // 2.把空对象和构造函数通过原型链进行链接
  newObj.__proto__ = Fun.prototype;
  // 3.把构造函数的this绑定到新的空对象身上
  const result = Fun.apply(newObj, args);
  // 4.根据构建函数返回的类型判断,
  //  如果是值类型,则返回对象,如果是引用类型,就要返回这个引用类型
  return result instanceof Object ? result : newObj;
}

function Person(name) {
  this.name = name;
}
Person.prototype.say = function () {
  console.log("hello world");
};
const p1 = newFun(Person, "yizhiyang");
p1.say();
console.log(p1);
image.png

2.递归实现深拷贝

let origin = {
  name: "张三",
  age: 18,
  say() {
    console.log("say hello");
  },
  arr: [[1, 2], 3, 4, 5],
  school: {
    className: {
      userName: "yizhiyang",
    },
  },
};

function deepClone(origin) {
  let newObj = {};

  // 判断是否是值类型,值类型终止
  if (typeof origin !== "object" || origin == null) {
    return origin;
  }

  //判断是对象还是数组
  newObj = origin instanceof Array ? [] : {};

  for (let key in origin) {
    let value = origin[key];

    newObj[key] = typeof value === "object" ? deepClone(value) : value;
  }
  return newObj;
}

const newOrigin = deepClone(origin);
console.log(origin);
console.log(newOrigin);
image.png

3. 原型链的继承

  • 原型链继承涉及到构造函数、原型和实例三的关系
    • 每一个构造函数都有一个原型对象
    • 原型对象又包含一个指向构造函数的指针
    • 实例则包含一个原型对象的指针
function Parent() {
  this.isShow = true;
  this.info = {
    name: "yizhiyang",
    age: 18,
  };
}
Parent.prototype.getInfo = function () {
  console.log(this.info);
};

function Child() {}

Child.prototype = new Parent();

let child1 = new Child();
child1.getInfo();
console.log("child1", child1);

let child2 = new Child();
child1.info.gender = "男";
child2.isShow = false;
console.log("child2", child2);
image.png
  • 让一个构造函数的原型是另一个类型的实例,那么这个构造函数new出来的实例就具有该实例的属性。
  • 优点:写法方便简洁,容易理解。
  • 缺点:对象实例共享所有继承的属性和方法。无法向父类构造函数传参。