简单介绍一下js中的构造函数、原型对象prototype、对象原型__proto__、原型链

构造函数
javascript 复制代码
	function Star (uname, age){
		this.uname = uname
		this.age = age
		
		this.sing = function(){ log('唱歌~') }
	}
	
	let xzq = new Star('薛之谦', 30)
	
	let ldh = new Star('刘德华', 20)
	log(ldh) // { uname: '刘德华', age: 20, sing: f }
	ldh.sing() // 唱歌~
	
	log(ldh.sing === xzq.sing) // false
复制代码
# 实例成员:构造函数内部,通过this添加的成员,如上面的:uname、age、sing
			实例成员,只能通过实例化的对象来访问,如:ldh.sing()才行,Star.sing()就不行

# 静态成员:在构造函数本身上,添加的成员,如:Star.sex = '男'
			静态成员只能通过构造函数访问,如:log(Star.sex) // 男
			不能通过实例化对象来访问(ldh.sex就不行)

# 构造函数 new 的执行过程
	1、new构造函数,可以在内存中创建一个空的对象
	2、this就会指向刚才创建的空对象
	3、执行构造函数里面的代码,就给这个空对象添加属性、方法
	4、返回这个对象(所以构造函数里面不用return)

prototype 原型对象
复制代码
# js规定,每一个构造函数都有一个prototype属性,这个prototype就是一个对象
  所以,我们可以把'公共的方法'添加到这个'原型对象prototype上'(原型对象prototype的作用就是共享方法)

  所以:公共的属性,定义到,构造函数里面
		公共的方法,定义到,原型对象prototype上
javascript 复制代码
	function Star (uname, age){
		this.uname = uname
		this.age = age
	}
	Star.prototype.sing = function(){ log('唱个歌') }
	
	let ldh = new Star('刘德华', 20)
	let xzq = new Star('薛之谦', 30)
	log(ldh.sing === xzq.sing) // true
	
	# console.log( ldh ) // 系统会自动,在对象的身上,添加一个'__proto__',指向构造函数的原型对象
	
	# prototype
		console.log( ldh.__proto__ === Star.prototype ) // true
方法的查找规则:
复制代码
	首先看`ldh对象`,它身上是否有sing()方法,如果有,就执行它的这个方法
	如果没有这个方法,但因为`__proto__`存在,就去`构造函数的原型对象prototype上`去找这个sing()方法
proto:对象原型
复制代码
	每个对象身上都有一个`__proto__`对象原型,指向`指向构造函数的原型对象prototype`
	之所以,对象可以使用`构造函数的原型对象prototype`上的属性、方法
	是因为,对象有`__proto__(对象原型)`的存在
	
	`__proto__对象原型` 和 `构造函数的原型对象prototype`是等价的
	
	`__proto__对象原型`的意义:在于为对象的查找机制提供一个方向,或者说一条线路,
	但它是一个非标准属性,因此实际开发中,不可用使用这个属性,它只是内部指向原型对象prototype

原型链
javascript 复制代码
	function Star(uname, age){
		this.uname = uname
		this.age = age
	}
	let ldh = new Start('刘德华', 123)
	
	log( ldh.__proto__ === Star.prototype ) // true
	
	log( Star.prototype.__proto__ === Object.prototype ) // true
	
	log( Star.prototype.__proto__ ) // null
原型链的查找规则
复制代码
	当访问一个对象的属性(方法)时,首先看这个对象本身有没有该属性,
	
	如果没有,就查找它的原型(也就是`__proto__对象原型`,指向的是,`prototype原型对象`)
	
	如果还没有,就查找,原型对象的原型(Object的原型对象)
	
	依次类推,直到找到Object为止(null)
	
	`_proto_对象原型`的意义:在于为对象的查找机制提供一个方向,或者说一条路线,
	但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,它只是内部指向原型对象prototype

可以通过原型对象,为JavaScript的(原来的)内置对象,进行扩展自定义的方法

如下:通过数组的原型对象,添加求和的方法

javascript 复制代码
	Array.prototype.sum = function(){
		console.log(this) // 指向它的调用者
		let sum = 0
		for(let i=0; i<this.length; i++){
			sum += this[i]
		}
		return sum
	}
	
	let arr = [1, 2, 3] // let arr = new Array(1,2,3)
	
	console.log(arr.sum()) // 6

constructor 指回 原来的原型对象
javascript 复制代码
// 定义一个构造函数Star
  function Star(uname, age) {
    this.uname = uname
    this.age = age
  }

  Star.prototype.sing = function () {
    console.log('唱歌~~')
  }

  // 对象.xxx:这样是向对象添加xxx属性,并不会覆盖这个对象
  Star.prototype.song = function () {
    console.log("我会唱歌")
  }

  Star.prototype.dance = function () {
    console.log("我会跳舞")
  }


  // 对象 = {}:这样是重新给对象赋值,会把原来的对象覆盖掉
  // 其实这里就是把 构造函数Star 的原型对象prototype 覆盖了,但是并不会影响uname、age在构造函数中定义的属性
  Star.prototype = {
    aaa() { console.log("我会唱歌aa") },
    bbb() { console.log("我会唱歌bbb") },
    // ....
    // ....
    // ....
  }

  // 手动用 constructor 指回原来的原型对象
  Star.prototype = {
    constructor: Star, // 指回原来的原型对象
    ccc() { console.log("我会唱歌ccc") },
    ddd() { console.log("我会唱歌ddd") },
    // ....
    // ....
    // ....
  }

  let ldh = new Star('刘德华', 123)
  console.log('ldh=', ldh) // ldh= Star {uname: '刘德华', age: 123}
  console.log('ldh.uname=', ldh.uname) // ldh.uname= 刘德华
  console.log('ldh.age=', ldh.age) // ldh.age= 123

  // ldh.sing() // Uncaught TypeError: ldh.sing is not a function
  ldh.song() // Uncaught TypeError: ldh.song is not a function

  // ldh.aaa() // Uncaught TypeError: ldh.aaa is not a function
  // ldh.bbb() //  Uncaught TypeError: ldh.bbb is not a function

  ldh.ccc() // 我会唱歌ccc.
  ldh.ddd() // 我会唱歌ddd
相关推荐
李长渊哦3 小时前
深入理解 JavaScript 中的全局对象与 JSON 序列化
开发语言·javascript·json
Senar5 小时前
如何判断浏览器是否开启硬件加速
前端·javascript·数据可视化
codingandsleeping5 小时前
一个简易版无缝轮播图的实现思路
前端·javascript·css
拉不动的猪6 小时前
简单回顾下插槽透传
前端·javascript·面试
爱吃鱼的锅包肉7 小时前
Flutter路由模块化管理方案
前端·javascript·flutter
风清扬雨7 小时前
Vue3具名插槽用法全解——从零到一的详细指南
前端·javascript·vue.js
海盗强7 小时前
Vue 3 常见的通信方式
javascript·vue.js·ecmascript
oscar9998 小时前
JavaScript与TypeScript
开发语言·javascript·typescript
橘子味的冰淇淋~8 小时前
【解决】Vue + Vite + TS 配置路径别名成功仍爆红
前端·javascript·vue.js
leluckys9 小时前
flutter 专题 六十三 Flutter入门与实战作者:xiangzhihong8Fluter 应用调试
前端·javascript·flutter