今天看啥  ›  专栏  ›  ForSakenSoul

JavaScript重要概念之构造函数,原型和原型链

ForSakenSoul  · 掘金  ·  · 2019-09-19 15:22
阅读 11

JavaScript重要概念之构造函数,原型和原型链

原型

概念

创建的每个函数都有一个prototype属性,该属性指向一个对象,这个对象就是原型对象。

构造函数,原型对象和实例对象的关系

// 声明一个构造函数
let Person = function( name,age) {
	this.name = name
  this.age = age
}
// 利用prtptype属性,将方法挂载到构造函数的原型对象上
Person.prototype.getName = function(){
	return this.name
}
// 利用构造函数 创建一个实例对象
let p1 = new Person('Tom',20)
复制代码
  1. 构造函数有一个prototype属性,指向原型对象。

实例对象有一个__proto__属性,指向原型
都指向同一个对象,称为原型对象或者原型。

p1.__proto__ === Person.prototype // true
复制代码
  1. 原型对象的constructor属性 指向构造函数
Person.prototype.constructor === Person // true
复制代码

知识点补充:consructor属性

概念

每个实例对象都从原型继承了一个constructor属性,该属性指向了用于构造此实例对象的构造函数。

var o = {};
o.constructor === Object; // true
var a = [];
a.constructor === Array; // true
var a = new Array;
a.constructor === Array // true
var n = new Number(3);
n.constructor === Number; // true
复制代码

改变函数的constructor

大多数情况下,此属性用于定义一个构造函数,并使用new和继承原型链进一步调用它。

function Parent() {}
// 在父类的原型对象上挂载方法
Parent.prototype.parentMethod = function parentMethod(){}
function Child() {}
Child.prototype = Object.create(Parent.prototype)
Child.prototype.constructor = Child
复制代码

原型链

每个对象都有一个原型对象,对象以其原型为模板,从原型上继承方法和属性。
原型对象也可能拥有它自己的原型对象,并从中继承方法和属性,一层一层,依次类推。
这种关系被称为原型链。
可以使用in操作符检测一个属性是否在其对象或者其原型上。会顺着原型链进行查找。
可以使用instanceof检测对象的原型。

构造函数

概念

构造函数本质上也是常规函数,只不过有两个规定

  • 首字母大写
  • 只能使用new操作符执行

语法

function User(name) {
	this.name = name
}
// 使用构造函数 
let user = new User()
复制代码

执行步骤

new操作符的执行步骤

  1. 声明一个中间对象
  2. 将中间对象的原型 属性(proto)指向构造函数的原型(prototype)
  3. 将构造函数的this指向该中间对象
  4. 返回该中间对象,即返回实例对象。

实现一个new操作符

// 如何使用
// 1. 声明一个构造函数
let Person = function (name,age) {
  this.name = name
  this.age = age
  this.getName = function(){
    return this.name
  }
}
// 2. 使用new操作符执行一个构造函数 创建实例对象
let p1 = new Person('Tom','age')
// 自己来实现一个new操作符  myNew
// new操作做的事情
// 1. 接收一个构造函数 作为参数, 返回一个对象
// 2. 声明一个中间对象,并最终返回这个对象
// 3. 将实例对象的原型指向构造函数的原型对象( 使用instanceof 能够检测到 对象的原型 )
function myNew(fun){
	// 参数判断  是否是函数
  // 声明一个中间对象 并最终返回它
  let res = { }
  // 执行一遍构造函数
  fun.apply(res,Array.prototype.slice.call(arguments,1))
	// 这句话做了什么?
  // 1. fun使用apply方法,相当于以res这个对象的this,去执行了一遍fun这个构造函数
  // 2. 由于构造函数可能需要多传参数,因此参数会保存在myNew这个函数的arguments里面,
  // arguments是一个类数组,不可调用slice方法,这里借用数组的slice方法,对参数进行分割
  // 剔除掉第一个参数,也就是fun,将剩余的参数,带入fun这个构造函数
  //3. 修改 res对象的原型 指向 
  // 要先判断下 是否为 null
  if(fun.prototype !==  null){
  	res.__proto__ = fun.prototype
  }
  return res
}
let p1 = myNew(Person,'Tom',11)
// js内部再经过处理,
//将 let p1 = New(Person,'Tom',11)  等效于 let p1 = new Person('Tom', 11);

复制代码



原文地址:访问原文地址
快照地址: 访问文章快照