函数的显示原型(prototype)
prototype 是函数内的一个对象空间(公共空间),每个函数都有一个,被称为显示原型,用于解决构造函数内存浪费(在调用方法时调用几次就会创建多少次内存空间)的问题。
- prototype 这个空间会在预编译的时候进行开辟 (只开辟一次)
- 利用 prototype 可以解决构造函数内存储的函数开辟多个内存空间的问题
- prototype 里面的方法可以直接通过对应的 [实例对象.方法名] 来访问
- 建议将对应的属性存入对应的构造函数,将对应的方法存入 prototype
Object.prototype.test = () => {
console.log('Objectd的test');
}
class Animal {
constructor() {
this.name = 'Animal来福'
}
run() {
console.log('Animal跑起来');
}
}
class Dog extends Animal {
constructor() {
super()
this.color = 'Dog黑白灰'
}
say() {
console.log('Dog叫汪汪');
}
}
let dog = new Dog()
let animal = new Animal()
let obj = new Object()
dog.say() // 实例对象.方法名
dog.run()
dog.test()
console.log(dog); // Dog {name: 'Animal来福', color: 'Dog黑白灰'}
class的机制
- 将 contructor 外部声明的函数自动加入到原型中
对象的隐式原型( __proto__ )
__proto__ 是对象的一个对象空间(实例对象也属于对象),他指向对应的构造函数的prototype,
原型链
- 在 __proto__ 中寻找属性的过程形成的链子 被称为原型链
- 对象赋值不遵从原型链 (如果存在属性那么对应的就修改 如果没有就添加)
【示例】
function Person() {
console.log(111)
}
let person = new Person()
console.log(Person.__proto__.__proto__.__proto__) //null
//函数的 __proto__ ƒ () { [native code] } ==> Object ==> null
console.log(person.__proto__) //Person的prototype 对象
console.log(person.__proto__.__proto__) //对象的__proto__ (Object.prototype)
console.log(person.__proto__.__proto__.__proto__)
//Object.prototype的__proto__==>null
// 找到对应null结束 Person -- Object -- null
-
模拟实现 instanceOf
instanceOf :(主要用于引用数据类型,基础值类型不可用)返回 true / false
- 用于判断某个实例是否属于某构造函数
- 在继承关系中用来判断一个实例是否属于它的父类型或者祖先类型的实例
语法:[对象] instanceof [构造函数]
特殊情况:
console.log(Number instanceof Number) // false console.log(String instanceof String) // false console.log(Fun instanceof Fun) // false,这里Fun指的是函数 console.log(null instanceof Object) // false,null不具有任何对象的特性,也没有__proto__属性
// instanceof模拟实现原型链查找
function MyInstanceof(son, father) {
while (son.__proto__) {
son = son.__proto__
if (son.constructor == father) {
return true
}
}
return false
}
console.log(MyInstanceof(dog, Dog)); //true
console.log(MyInstanceof(dog, Animal)); //true
console.log(MyInstanceof(dog, Object)); //true
// instanceof
console.log(dog instanceof Dog); //true
console.log(dog instanceof Animal); //true
console.log(dog instanceof Object); //true
-
模拟实现new关键词
// 模拟实现new
function fn() {
this.name = name
}
function MyNew(fn) {
let obj = {}
obj.__proto__ = fn.prototype
fn.call(obj)
return obj
}
console.log(myNew(fn));
【一些内置对象里面的方法大部分是放在原型上】*
如:forEach、reduce、some、find等
模拟数组的高阶函数:forEach、find、findIndex、reduce、reduceRight、some...
- forEach
Array.prototype.MyForEach = function(callback) {
if (typeof callback != 'function') {
throw new Error()
}
for (let i = 1; i < this.length; i++) {
callback(this[i], i, this)
}
}
new Array(1, 5, 3, 7, 9, 2, 1).MyForEach((v, i, arr) => {
console.log(v, i, arr);
})
- find、findIndex
// find返回第一个符合条件的值
Array.prototype.MyFind = function(callback) {
if (typeof callback != 'function') {
throw new Error()
}
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
return this[i]
}
}
}
let res = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyFind((v, i, arr) => {
return v > 5
})
console.log(res);
// findIndex返回第一个符合条件的下标
Array.prototype.MyFindIndex = function(callback) {
if (typeof callback != 'function') {
throw new Error()
}
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
return i
}
}
return -1
}
let res1 = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyFindIndex((v, i, arr) => {
return v > 5
})
console.log(res1);
- reduce、reduceRight
// reduce
Array.prototype.MyReduce = function(callback, value) {
if (typeof callback != 'function') {
throw new Error()
}
let index = 1
let prev = this[0]
if (value) {
prev = value
index = 0
}
for (; index < this.length; index++) {
prev = callback(prev, this[index], index, this)
}
return prev
}
let res = new Array(1, 5, 2, 4, 3, 6, 8).MyReduce((prev, current, i, arr) => {
return prev + current
}, 5)
console.log(res);
// reduceRight
Array.prototype.MyReduce = function(callback, value) {
if (typeof callback != 'function') {
throw new Error()
}
let index = this.length - 2
let prev = this[this.length - 1]
if (value) {
prev = value
index = this.length - 1
}
for (; index >= 0; index--) {
prev = callback(prev, this[index], index, this)
}
return prev
}
let res1 = new Array(1, 5, 2, 4, 3, 6, 8).MyReduce((prev, current, i, arr) => {
console.log(prev, current, i, arr);
return prev + current
}, 5)
console.log(res1);
- some、every
//every
Array.prototype.MyEvery = function(callback) {
if (typeof callback != 'function') {
throw new Error()
}
for (var i = 0; i < this.length; i++) {
if (!callback(this[i], i, this)) {
return false
}
}
return true
}
let res = new Array(1, 5, 2, 4, 3, 6, 8, 6).MyEvery((v, i, arr) => {
return v > 5
})
console.log(res);
// some
Array.prototype.MySome = function(callback) {
if (typeof callback != 'function') {
throw new Error()
}
for (var i = 0; i < this.length; i++) {
if (callback(this[i], i, this)) {
return true
}
}
return false
}
let res1 = new Array(1, 5, 2, 4, 3, 6, 8, 6).MySome((v, i, arr) => {
return v > 5
})
console.log(res1);
继承
class 继承实现 extends (es6):可以继承静态方法 *
class Animal {
constructor(name) {
this.name = name
}
}
class Dog extends Animal {
constructor(name, color) {
super(name)
this.color = color
}
}
let dog = new Dog('来福', 'pink')
console.log(dog); //Dog {name: '来福', color: 'pink'}
构造函数的继承 (继承不了静态的方法和属性)
- 原型链继承:将父类对象放在子类的原型链上
缺点:因为不能进行初始化赋值的操作,所以继承父类的属性值为undefined;
子类的原型要写在原型继承之后,否则会被覆盖。
- 对象冒充:将对应的父类构造函数当作普通函数执行,传入对应的子类构造函数中的 this
缺点:获取不了父类原型上的内容
- 组合继承:原型链继承 + 对象冒充
缺点:会重复继承父类原型的属性和方法
- 寄生组合继承:主要寄生原型(将父类原型对象加入到子类的原型上) + 对象冒充
// 父类构造
function Father(name, age) {
this.name = name
this.age = age
}
// 子类构造
function Son(height) {
this.height = height
}
原型链继承
Son.prototype = new Father()
let son = new Son(170)
console.log(son);
// Son {height: 170}
// height: 170
// [[Prototype]]: Father
// age: undefined
// name: undefined
对象冒充
function Son(height, name, age) {
Father.call(this, name, age)
this.height = height
}
let son = new Son('170', 'tom', 50)
console.log(son);
// Son {name: 'tom',age: 50,height: '170'}
// age: 50
// height: "170"
// name: "tom"
组合继承
function Son(height, name, age) {
Father.call(this, name, age)
this.height = height
}
Son.prototype = new Father()
let son = new Son('170', 'tom', 50)
console.log(son)
// Son {name: 'tom',age: 50,height: '170'}
// age: 50
// height: "170"
// name: "tom" [
// [Prototype]]: Father
// age: undefined
// name: undefined
寄生组合继承
function Son(height, name, age) {
Father.call(this, name, age)
this.height = height
}
Son.prototype = Object.create(Father.prototype)
let son = new Son('170', 'tom', 50)
console.log(son instanceof Son); //true
console.log(son);
// Son {name: 'tom',age: 50,height: '170'}
// age:50
// height:"170"
// name:"tom"
// [[Prototype]]:Father