原型编程的基本规则:

  1. 所有的数据都是对象
  2. 要得到一个对象,不是通过实例化类,而是找到一个对象作为原型并克隆它
  3. 对象会记住它的原型
  4. 如果对象无法相应某个请求,它会把这个请求委托给它自己的原型

直接上图

一、继续说说构造函数

  1. 构造函数只有一个特点:函数名是大驼峰式
  2. 构造函数必须用 new 才能生产一个对象
  3. 构造函数不停的调用,可以生产出多个相似且独立的对象
  4. 生成对象这个过程,称之为 实例化对象

二、原型链属性的增删改

通过对象修改原型的东西不太现实,因为后代不可能修改祖先的东西

只有通过 Person.prototype.xxx 增加东西到原型上

Person.prototype.name = '张三';
function Person() {}var person = new Person();
delete Person.prototype.name; // true 删除成功
Person.prototype.name = '李四'; //=> 只能通过这种方式修改原型上的东西

三、原型上的 constructor 属性

  1. constructor 会返回构造这个对象的构造函数
function Person() {}var person = new Person();
console.log(person.constructor); //=> Person()
  1. constructor 可以手动更改
Person.prototype = {constructor: Car // 更改原构造函数的 constructor
}function Person() {}function Car() {}var person = new Person();
  1. constructor 再次对象实例化
function Person(name, age) {this.name = name;this.age = age;
}var person = new Person('mary', 18);
var person1 = new person.constructor('smith', 20); // 再次使用 construcor 来实例化
console.log(person.constructor === person1.constructor); // true
  1. 通过把实例对象赋值给原型对象 来延长原型链
const Person = function (name, age) {this.name = name;this.age = age;
};Person.prototype.sayName = function () {return this.name;
}const Student = function () {};Student.prototype = new Person(); // 把 Person 的实例对象 赋值给 Student 的原型对象
Student.prototype.constructor = Student; // 把 构造者 改为 Studentconst me = new Student();

结果

此时的原型链有四层了,普通对象只有三层

  1. 构造函数里面的 this
function Person() {// var this = {//     // }// 这里面的 this, 指向即将实例化的那个对象console.log(this); // Person {...}
}var person = new Person();

四、__ proto __ 属性

  • __ proto __干啥的???
Person.prototype.name = '张三';
function Person() {// var this = {//     __proto__ : Person.prototype// };// __proto__ 指向的是对象的原型// 原对象里面是没有 name 属性的
}var person = new Person();
console.log(person.name); // 张三 --> 在原型上找到了 name 属性

这就是调用一个对象的属性,如果对象属性里面没有的话,就会上原型里面找的原因。

  • 更改 __ proto __ 指向
Person.prototype.name = '李四';
function Person() {// 原来的 person.__proto__ 指向的是原型对象
}var obj = {name : '张三'
};var person = new Person();
person.__proto__ = obj; // __proto__ 属性是可以更改的
console.log(person.name); // 张三
  • 原型链的连接点 __ proto __
Grand.prototype.name = '张三';
function Grand() {}var grand = new Grand();Father.prototype = grand;
function Father() {}var father = new Father();Son.prototype = father;
function Son() = {}var son = new Son();
console.log(son.name); // 张三
// 但是如果 Grand 上面都没有的话就会上原型链的终端 Object.prototype 上面去找,如果还是没有就会打印 null。!!!

总结: 每一个对象都有一个 __proto__ 属性, 指向该对象的原型. 实例后通过对 __proto__ 属性的访问 去对 prototype 对象进行访问; 原型链是由原型对象组成的, 每一个对象都有 __proto__ 属性, 指向创建该对象的构造函数的原型, 然后通过 __proto__ 属性链接起来, 组成一个原型链, 用来实现继承和共享属性!

五、Object.create(prototype)方法

  • 还可以用 Object.create(prototype) 方法创建对象
var obj = {name : '张三',age : 18
}var obj1 = Object.create(obj);
  • 模拟构造函数
Person.prototype.name = '张三';
function Person() {}var person = Object.create(Person.prototype);
  • 判断题:全部对象最终都会继承自 Object.prototype
var obj = Object.create(null); // 构造出一个空的对象,里面啥都没有
// 所以是错的,应该是绝大多数对象最终都会继承 Object.prototype

这就是为什么 undefined.toString() / null.toString() 会报错的原因了

undefined / null 没有原型,也不会经过包装类

  • 123.toString() 也会报错

因为 JS 会认为 123 后面有 . 点,就是一个浮点型,而浮点型后面是不能跟字母的

  • JS 重写
var num = 123;
// num.toString(); // new Number(num).toString(); --> Number(); 原型上面有 toString() 方法;Number.prototype.toString = function() {// 虽然原型上有这个方法,但是我有重新写了一个不同功能的 toString() 方法console.log('that change is true');
}// Number 的原型指向 Object.prototype
// NUmber.prototype.__proto__ = Object.prototype// 包括 Object.prototype.toString() 也可以更改
Object.prototype.toString = function() {console.log('that change is true too');
}

原型上有,但我自身写了一个和原型上那个方法同名,但是不同功能的方法

Object.prototype.toString = function() {return 'i am win'; //=> 主要还是看 return 的返回值
}
Person.prototype = {// toString : function() { // 把系统自带的 toString() 方法覆盖了//     return 'hello world';// }
}
function Person() {}var person = new Person();
person.toString(); // i am win
  • toString() 方法的
object.prototype.toString();
Number.prototype.toString();
String.prototype.toString();
Boolean.prototype.toString();

六、 探讨 document.write() 方法

var obj = {};document.write(obj); // [object Object]
// 但实际上是 toString() 的结果
document.write(obj.toString()); // [object Object]
// 说明网页面输出数据,都会调用 toString() 方法// 再次证明
var obj = Object.create(null); // 让原型、方法那些都清空
document.write(obj); // 报错var obj = Object.create(null);
obj.toString = function() { // 再次检测 document.write() 是不是调用了 toString() 方法return 'hello world';
}document.write(obj); // hello world

js 原型以及原型链相关推荐

  1. 浅谈JS原型与原型链(一)

    最近学习JavaScript原型与原型链的时候,被这块知识烧得脑壳疼,prototype与__proto__混淆不清.网上各种图解,都画的好复杂,绕老绕去,不明所以,看得越来越糊涂.还是亲自动手敲敲, ...

  2. JS原型与原型链终极详解

     一. 普通对象与函数对象   JavaScript 中,万物皆对象!但对象也是有区别的.分为普通对象和函数对象,Object ,Function 是JS自带的函数对象.下面举例说明 functi ...

  3. JS题目总结:原型链/new/json/MVC/Promise

    JS题目总结:原型链/new/json/MVC/Promise 1原型链相关 解读: 上图中,Object,Function,Array,Boolean都是构造函数 第一个框: object是实例对象 ...

  4. js原型和原型链_重学js --原型与原型链

    一.什么是原型: .每个对象都有一个__proto__属性,并且指向它的prototype原型对象 每个构造函数都有一个prototype原型对象 prototype原型对象里的constructor ...

  5. JS难点剖析-原型原型链

    2019独角兽企业重金招聘Python工程师标准>>> js的原型&原型链&闭包,在很多人看来是区分JS程序员水平的关键知识点,当然对这句话我不是十分赞同.但是掌握这 ...

  6. js原型和原型链_JS里的原型和原型链

    JS里的原型与原型链 原型 原型和原型链的目的是解决构造函数生成的对象内共同属性重复生成的问题,使其更高效.在下面这个例子里每次生成一个实例对象都要生成一个mmm方法,没有必要,完全可以共享. 构造函 ...

  7. (五)JS基础知识二(通过图理解原型和原型链)【三座大山之一,必考!!!】

    JS基础知识二(原型和原型链) 提问 class 继承 类型判断(instanceof) 原型 原型关系 基于原型的执行规则 原型链 说明 提问 如何准确判断一个变量是不是数组 class的原型本质 ...

  8. 最详细的讲解 JS 原型与原型链

    文章目录 一. 普通对象与函数对象 二. 构造函数 三. 原型对象 四. proto 五. 构造器 六. 原型链 七. Prototype 总结 一. 普通对象与函数对象 JavaScript 中,万 ...

  9. js原型、原型链、作用链、闭包全解

    https://www.2cto.com/kf/201711/698876.html [对象.变量] 一个对象就是一个类,可以理解为一个物体的标准化定义.它不是一个具体的实物,只是一个标准.而通过对象 ...

  10. [js] js怎样避免原型链上的对象共享?

    [js] js怎样避免原型链上的对象共享? 组合继承 优势 公有的写在原型 私有的卸载构造函数 可以向父类传递参数 劣势 需要手动绑定constructor 封装性一般 重复调用父类性能损耗

最新文章

  1. docker安装mysql并实现远程访问
  2. Hlink的Analysis基本搞定了
  3. oracle第一次使用语句创建作业失败记
  4. linux长期版本维护内容,[图]Linux Kernel 4.20首个维护版本更新发布 已稳定可广泛部署...
  5. mysql 织梦 优化,优化分析:分享织梦搭建和后台优化设置
  6. Yum出错Error: Cannot find a valid baseurl for repo: addons
  7. 线性表的Java实现--链式存储(双向链表)
  8. springboot+flowable第二节(流程基本操作)
  9. Android 7.0 隐式广播-监听网络变化
  10. Java 中 == 和equals()方法的不同点
  11. oracle rac ora 12547,oracle11g RAC 下DBCA建库失败:ORA-12547: TNS:lost contact
  12. linux 目前运行的服务,Linux系统服务
  13. spark在集群上运行
  14. 进阶 09 Map集合
  15. mysql 改变 执行计划_诡异的MySql执行计划的更改
  16. mysql主从延迟设置
  17. 数据结构与算法之美-队列
  18. 阻塞、非阻塞、同步、异步的区别
  19. IT桌面运维常识系列 - MDT
  20. 音视频播放器—快进快退及逐帧播放

热门文章

  1. 智能关机软件 c语言,智能关机软件
  2. java 类数组_Java常用类-字符串、日期类、算法及数组工具类等
  3. php数据类型_PHP数据类型能力问题和解答
  4. 驳《阿里「Java开发手册」中的1个bug》?
  5. Java中所有锁介绍
  6. Spring Boot(九)Swagger2自动生成接口文档和Mock模拟数据
  7. python根据坐标点拟合曲线绘图
  8. Jeston TX2安装Ubuntu系统
  9. 复习----使用链表实现栈(后进先出)及迭代
  10. python远程登录并执行命令_Python - 远程SSH执行命令