关于构造函数和原型的实验笔记
关于构造函数,我想到一个比方。b 本是B生的,但是B断绝了和他的母子关系, A无子女,决定领养b,于是A就成了b的继母,也就是b法律上的妈妈。你问b的妈妈叫什么, 就相当于问b的构造函数是谁。这种关系很容易改变,立个什么字据或证明就可以了。 而原型就相当于是b身上的基因,这是领养这种关系改变不了的,属于先天得到的。 除非把它的基因都给改了,那时自然也就验出B是它的亲妈了。
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 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 | //学校 function School (name) { this .name = name; this .teachers = []; this .level = function (){ console.log( 'University' ) } } //添加到原型上的属性 School.prototype.students = []; //学校功能--介绍 School.prototype.show = function (){ console.log( this .name+ ':很棒的学校!' ) this .teachers.forEach( function (teach){ console.log( this .name + '-' + teach); }) } //学校功能---招聘老师 School.prototype.recruit = function (name){ this .teachers.push(name); } //学校功能---招生 School.prototype.enroll = function (name){ this .students.push(name); } //通过构造函数的方式创建对象 var ts = new School( 'Tsinghua University' ); //此时School就是ts的构造函数 var bj = new School( 'Beijin University' ); //此时School就是bj的构造函数 //通过构造函数创建的对象,注意两个问题 //1 构造函数内的属性和方法是不被共享的 //2 原型上的属性和方法是共享的 ts.recruit( 'frog' ); // frog 是ts这个学校的老师 bj.recruit( 'Aaron' ); // Aaron 是bj这个学校的老师 ts.show(); // frog只出现在ts中 bj.show(); //Aaron只出现在bj中 //说明构造函数内声明的属性不被共享 console.log(bj.teachers === ts.teachers); // false //说明构造函数内声明的方法不被共享 console.log(bj.level === ts.level); //false; //说明teachers放在构造函数内是对的,各学校的老师互不影响 ts.enroll( 'Tom' ); //只给ts学校招生 console.log(bj.students) //ts学校没有招生,也有这个学生了 bj.enroll( 'Jek' ); console.log(ts.students) //bj学校招的学生,在ts也有 //说明原型上的方法是共享的 console.log(bj.enroll === ts.enroll) // true //说明原型上的属性是共享的 console.log(bj.students === ts.students) // true; //小结: 方法尽量写在原型上,可以节省资源,引用类型的属性尽量写在构造函数内,避免污染; //构造函数的问题 function A(){ this .name = 'A' ; } function B(){ this .name = 'B' ; } var a = new A; console.log(a.constructor===A) // true //用A的实例对象替换B的原型对象 B.prototype = new A; var b = new B; console.log(b.constructor===B) // false console.log(b.constructor===A) // true //说明重写原型对象会产生构造函数指向的问题 //修正构造函数为B B.prototype.constructor = B; console.log(b.constructor===B) //true //constructor是挂在prototype上的,重写prototype,也会自动改写constructor console.log(b.isPrototypeOf(B)) //false; console.log(Object.getPrototypeOf(b)) // A //修正contructor也改变不了prototype的引用关系 //这种写法也会产生B的构造函数指向有问题 B.prototype = { //... } //推荐这样写 A.prototype.getName = function (){ console.log( this .name); } function C(){ this .name = 'C' ; } C.prototype.getAge= function (){ console.log( 'c age 18' ) } var c = new C; //只改变构造函数 C.prototype.constructor = A; console.log(Object.getPrototypeOf(c)) // A console.log(c.isPrototypeOf(C)) // false console.log(c.isPrototypeOf(A)) // false console.log(c) //C; //c.getName(); // undefined c.getAge(); //c age 18 //小结: 只要改变了对象的原型,那么它的造函数就会自动改变, //只改变构造函数的指向,原型的判断不准确了,但是没有被改写。 |
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?