Kros的博客 Kros的博客
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云

Kros

凡心所向,素履以往,生如逆旅,一苇以航
首页
  • CSS
  • 工具
  • Vue
  • js
  • Vue3
  • 算法
  • 折腾笔记
一言
  • 分类
  • 标签
  • 归档
码云
  • CSS

  • JavaScript

    • 兼容ie7的水平无限滚动
    • 节流防抖
    • 数组乱序
    • 开启全屏
    • 数据类型
    • 变量提升
    • this调用指向
    • 原型及原型扩展
    • js获取元素属性精度问题
    • setTimeout和setInterval
    • 数组判断
    • dom节点添加或插入元素
    • var、let和const的区别
    • 判断ellipsis是否省略生效
    • 使用ResizeObserver监听元素size变化
    • js自定义事件
    • use strict详解
    • 私有属性
    • js实现类的方式
    • call和apply的理解和使用
    • js失焦和点击事件顺序冲突
    • js中不常见但非常实用的运算符
    • for of和for in的区别
    • defer和async的区别
    • promise值穿透
    • js为什么会出现数字精确度丢失
    • js禁用F12开发者模式
    • 使用scrollTop和scrollTo滚动到目标位置
    • js实现打字机效果
    • 多种方式实现数组去重
    • 替换使用setTimeout
    • encodeURI和encodeURIComponent的区别
    • canvas实现弹跳小球
    • js实现跨标签页通信
    • 事件循环与微任务、宏任务
    • 浏览器存储数据方式
    • 常见的meta元数据使用
    • 使用InterSectionObserver判断元素区域(chatGPT)
  • 工具

  • Vue

  • antdv踩坑记录

  • Vue3

  • 前端
  • JavaScript
kros
2021-02-24

原型及原型扩展

prototype翻译为“原型”,js中所有function的对象都有一个prototype属性,这个属性本身是一个object对象,我们可以在上面添加属性和方法。同时,prototype上定义的方法和属性统一原型链上的对象皆可调用。 修改我的上一篇this指向调用如下

function Animal(name) {	
    this.name = name;	
	// 将say函数挂载到原型链上
	//this.say = function() {
	//	console.log('I\'m ' + this.name || '');
	//	return this;
	//}
}
// 
Animal.prototype.say = function() {
	console.log('I\'m ' + this.name || '');
	return this;
}
let ani = new Animal('牛');
ani.say();

function Fish(name, food) {
	//Animal.call(this, name);
	this.food = food;
	this.eat = function() {
	    console.log('I eat ' + this.food || '');
	}
}

// 将Fish指向Animal原型,获得say方法和name属性
Fish.prototype = new Animal('鲤鱼');

let carp = new Fish('水草');
carp.say().eat();

// Fish的say方法和Animal的say方法是同一个
console.log(carp.say == ani.say); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32

按照上面的写法,在animal的原型上挂载了say方法,同理我们将aniaml整体挂载到Fish原型上,那么Fish的原型上就会有name和say两个。正常情况下我们是不想要name属性到原型上的,所有我做出如下修改:

function Fish(name, food) {
	// 获取Animal的name属性
	Animal.call(this, name);
	this.food = food;
	this.eat = function() {
	    console.log('I eat ' + this.food || '');
	}
}
// Fish原型链指向Animal原型链,只获取say方法
Fish.prototype = Animal.prototype;
1
2
3
4
5
6
7
8
9
10

因为function本身就是object所以所有的prototype最终会指向Object.prototype,从而形成一条条原型链。原型链上的属性或方法会从上到下继承,你可以使用原型对象的方法或属性也可以自定义覆盖原型属性,玩法非常灵活。

在js中很多方法都是通过原型来实现的,比如说常用数组和字符串类型的内置方法其实都是挂载到原型上的,查看MDN文档 可以清楚看到。

demo

通过原型我们能进行自定义扩展,拿我使用的Vue框架来说使用亦是很频繁。在main.js中我们可以使用Vue.prototype挂载自定义属性,通常我们会将全局的api请求、国际化、Vuex等挂载到Vue的原型上,那么在Vue环境中通过this即可调用

import Vue from 'vue'
import App from './App'
import api from './api'

Vue.prototype.$api = api
Vue.prototype.$store = store
const app = new Vue({
    ...App
})
app.$mount()
1
2
3
4
5
6
7
8
9
10

*注意:*实例对象没有prototyp属性,所有对Vue new出来的实例app不能设置prototype

Vue我们使用的$on、$emit、$set、$destroy等方法都是通过原型挂载的,在Vue源码vue/src/core/instance/state.js、vue/src/core/instance/lifecycle.js、vue/src/core/instance/events.js中都可以看到挂载记录

除开prototype我们还有一种隐式原型__proto__,不同于prototype只在函数中,__proto__存在于所有的对象中。使用它来访问已经实例化对象的prototype属性,两者使用有不少的区别。

  • 实例对象没有prototyp属性
  • 实例对象的__proto__指向对象Person的prototype
  • 实例对象__proto__等同于Object.getPrototypeOf(实例对象)、对象的__proto__等同于Object.getPrototypeOf(对象)
function Person(name) {
  this.name = name
}
let person1 = new Person('张三')
console.log(person1.prototype) // undefined
console.log(person1.__proto__) // {} 
console.log(person1.__proto__ === Person.prototype) // true 
console.log(person1.__proto__ === Object.getPrototypeOf(person1)) // true
console.log(Person.__proto__ === Object.getPrototypeOf(Person)) // true

1
2
3
4
5
6
7
8
9
10
上次更新: 2025/09/05, 8:09:00
this调用指向
js获取元素属性精度问题

← this调用指向 js获取元素属性精度问题→

最近更新
01
Find the next perfect square
09-05
02
Regex validate PIN code
09-05
03
Find the odd int
09-05
更多文章>
Theme by Vdoing | Copyright © 2020-2025 kros king
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式
icon-heart-o icon-heart icon-infinity icon-pause icon-play link next prev