1. 认识函数 + 原型定义
(1)函数也是一个对象,当真正开始执行函数,执行环境【开发时为浏览器或控制台】会为函数分配一个函数对象变量空间和函数对象空间,函数对象变量用函数名表示,存在栈空间中, 函数对象空间是在堆中开辟的一个内存空间,这个空间中有一个默认的 prototype 属性,这个 prototype 属性就是一个原型对象属性【也叫对象变量】
constructor
: 对象空间地址
__proto__
: 上一级原型对象空间首地址
(2) 函数和构造函数的区别
当通过 new 函数()时,此刻这个函数就是构造函数【 日后会演变成TS 类的构造器】
(3)定义:原型【 prototype ] 是定义函数由 JS 自动分配给函数的一个可以被所有构造函数实例对象变量共享的对象变量【也叫对象属性】
2. 如何访问原型对象空间上的属性和方法
(1)构造函数所有实例对象都可以访问型对象空间上的属性和方法 【每一个实例都有默认的 __proto__
属性,这个 __proto__
属性指向原型对象空间】
(2)关于__proto__:new 在创建新对象的时候,会赋予新对象一个属性指向构造函数的 prototype 对象空间,这个属性就是 proto
__proto__指向原型对象空间
(3) 可以直接通过构造函数.prototype 对象属性来访问原型对象空间上的属性和方法
3. 构造函数实例【也叫对象】如何访问原型对象空间上的属性和方法
(1)构造函数实例访问一个属性和方法,首先从实例空间中查找【当执行环境执行 new 构造函数()时,构造函数中通过 this 定义的属性和方法会分配在这个空间中】,如果找到该属性和方法,就停止查找,表示找到了;如果没有找到,就继续在该实例的原型对象空间中去查找该属性和方法 【实例中默认的 proto 对象 属性指向原型对象空间】
/** * 定义老师的信息 * @param _name 姓名 * @param _type 类型 * @param _age 年龄 */ function teacher(_name, _type, _age) { this.name = _name this.type = _type this.age = _age } teacher.prototype.students = ['小何', '小罗', '小陈'] teacher.prototype.show = function () { console.log(`老师:${ this.name }, 是:${ this.type }, 年龄:${ this.age }`) console.log(`共同的学生有:${ this.students }`) } const ll = new teacher("老六", '英语老师', 28); ll.show() /* * * 老师:老六, 是:英语老师, 年龄:28 * 共同的学生有:小何,小罗,小陈 * */ // 可如果在原型上修改了其中的一个变量 teacher.prototype.type = "abc"; const xh = new teacher("小何", ‘编程老师’, 18); console.log(xh); /** * 这里的type还是先会去实例空间中寻找,如果找不到,才会去原型上进行寻找 * 所以,这里打印的还是 * { * name: "小何" * type: "编程老师" * age: 18 * } */ // 可是当type这个属性不存在的时候,就会去原型上寻找 function teacher(_name, _type, _age) { this.name = _name // this.type = _type this.age = _age } // 可如果在原型上修改了其中的一个变量 teacher.prototype.type = "abc"; const ww = new teacher("wangwu", '体育老师', 45) console.log(ww.type) // 'abc' 复制代码
(2)实例正是借助自身的 __proto__
对象属性 来查找原型对象空间中的属性和方法,有点像儿子去和爸爸要他没有的东西一样。】
4. 增加或修改原型对象的属性或方法后, 所有的实例或叫对象立即可以访问的到 【但创建实例后再覆盖原型除外】
function teacher(_name, _type, _age) { this.name = _name this.type = _type this.age = _age } teacher.prototype.students = ['小何', '小罗', '小陈'] const zs = new teacher("张三", "语文老师", 18); teacher.prototype.students.push("小谢"); console.log(zs.students); // ['小何', '小罗', '小陈', '小谢'] // -->但创建实例后再覆盖原型除外 复制代码
5. 高频面试题:创建实例后再覆盖原型,实例对象无法访问到,为什么?
let obj = { a: 1, b: 2 } obj.a = 'list' obj.c = 123 let obj2 = obj obj = { addr: '深圳' } console.log("obj:", obj) // {addr: "深圳"} 指向变了 console.log("obj2:", obj2) // { a: 'list', b: 2, c: 123 } 复制代码
6. 当obj2指向的空间里的值修改了,对应指向的obj也会一并修改吗?
let obj = { a: 1, b: 2 } let obj2 = obj obj.a = 3 console.log('obj:', obj) // { a: 3, b: 2 } console.log('obj2:', obj2) // { a: 3, b: 2 } 复制代码
因为这两个变量指向的都是同一个内存空间