1. 构造函数与原型

先了解一个概念:

类就是对象的模板,对象就是类的实例。

在构造函数内部的this指向它的实例对象。

2. new关键字

这个也是面试常考的知识点

在实例化构造函数时,做了什么?或者说在JavaScript中new

  1. 创建空对象 var zs = { }

  2. 将构造函数内部的this指向空对象 this -> zs

  3. 把属性和方法挂载到实例对象上。 zs.name zs.age zs.sing()

  4. 隐式返回新对象。

3. 实例成员与静态成员

  • 实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问。
  • 静态成员:在构造函数本身上添加的成员称为静态成员,只能由构造函数本身来访问。
  var arr = new Array()console.dir(arr);console.dir(Array);

4. 构造函数与静态成员

同一个函数,会在内存中保存多份,会造成内存的浪费。

<script>function Cup(color, size) {this.color = colorthis.size = sizethis.save = function () {console.log("储水");}}var mycup1 = new Cup("紫色", "3400ml")var mycup2 = new Cup("绿色", "400ml")console.log(mycup1);console.log(mycup2);mycup1.save()mycup2.save()引用数据类型,比较的是内存中的地址console.log(mycup1.save == mycup2.save);输出false地址不同,造成浪费
</script>

引用性数据类型比较的是地址

5. 原型对象Prototype/[__proto__]

是构造函数的属性;

是Object类

构造函数的原型protoeype,作用是实现对象和属性共享,解决内存浪费问题。

每个一构造函数都有一个protoeype属性指向一个对象,这个prototype就是一个对象,这个对象的所有属性和方法,都会被构造函数所有。

一般情况下,我们公共属性放在构造函数里面,公共的方法我们放到原型对象身上。

原型对象里面的this指向的就是这个实例对象

作用:可以通过原型对象,对原来的内置对象进行拓展自定义的方法。

  function Cup(color, size) {this.color = colorthis.size = sizeCup.prototype.save = function () {console.log("储水");}Cup.prototype.fill = function () {console.log("储水");}}

6. __proto__

对象能够访问原型对象中的方法:

原因:对象的_ _ proto_ _ 属性指向构造函数的prototype/原型对象

名称:对象原型

  • __proto__对象原型和原型对象prototype是等价的
  • __proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说是一条路线,但是它是一个非标准属性,因此实际开发中,不可以使用这个属性,他只是内部指向原型对象prototype.

非标准:

不能使用,只能直接看他指向的结果,不能设置,只能直接访问

7. constructor属性

对象原型(__proto__)和构造函数(prototype)原型对象里面都有一个属性constructor属性,constructor我们称为构造函数,因此它指回构造函数本身。

  • 作用:主要用于记录该对象引用哪个构造函数,它可以让原型对象重新指向原来的构造函数。

constructor属性在那里可以访问:

  1. __proto__有constructor属性

  2. 原型对象/prototype有constructor属性

我们称constructor为构造函数。

使用:当以对象的形式修改原型对象的内容时,会发现修改后的属性把原来的属性覆盖掉了,这时候就需要重新设置一下constructor属性,并指挥回原来的构造函数。

  function Cup(color, size) {this.color = colorthis.size = size}Cup.prototype = {constructor: Cup,save: function () {console.log("储水");},warn: function () {console.log("保温");}}

(以对象的形式,修改了原型对象中的内容,这样修改后的原型对象constructor就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个constructor指向原来的构造函数)

8.原型链

JavaScript对象,都有__proto__属性,指向原型对象。

(mycup,Cup,Object,null)

  • 作用:js中在查找对象和属性的方式时,遵循的一条链式规则。

    • 当访问一个对象的属性(包括方法)时,首先找到这个对象自身有没有该属性
    • 如果没有就查找它的原型(也就是__proto__指向的prototype原型对象)
    • 如果还没有就查找原型对象的原型(Object原型对象)
    • 以此类推一直找到Object为止(null)
    • __proto__对象原型的意义在于为对象成员查找机制提供了一种方向,或者说一条路线。

如果原型链找不到属性,undefined。如果找不到方法,会报错。

  • 关系:instance.constructor.prototype == instance.__proto__

  • 特点:JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。

小例子:

  function Cup(color, size) {this.color = colorthis.size = size}Cup.prototype = {constructor: Cup,save: function () {console.log("储水");},warn: function () {console.log("保温");}}var mycup = new Cup("粉色", "1500ml")console.log(mycup);console.log(mycup.__proto__ == Cup.prototype);console.log(mycup.__proto__.constructor); //指向当前的构造函数console.log(Cup.prototype.constructor); //指向当前的构造函数//验证原型链console.log(mycup.__proto__ == Cup.prototype);console.log(Cup.prototype.__proto__ == Object.prototype);console.log(Object.prototype.__proto__ == null);var arr = [1, 2, 3]var arr1 = new Array(1, 2, 3)console.log(arr, arr1);arr1.push(4)Array.prototype.sum = function () {var total = 0;for (var i = 0; i < this.length; i++) {total += this[i];}return total}console.log(arr.sum());console.log(arr1.sum());

9.继承

JavaScript如何实现继承

  • 构造继承
  • 原型继承
  • 实例继承
  • 拷贝继承
  • 原型prototype机制或apply和call方法去实现较简单,建议使用构造函数与原型混合方式
function Parent(){this.name = 'wang';
}function Child(){this.age = 28;
}Child.prototype = new Parent();//继承了Parent,通过原型var demo = new Child();
alert(demo.age);
alert(demo.name);//得到被继承的属性

ES6:利用extends实现继承

组合继承:构造函数+原型对象

es5继承:构造函数+原型对象

  //es5继承:构造函数 + 原型对象//1. 利用构造函数继承属性function Father(name, age) {this.name = namethis.age = age}Father.prototype.work = function () {console.log("工作");}function Son(name, age, gender) {Father.call(this, name, age);this.gender = gender;}Son.prototype = new Father() //子构造函数的peototype = new 父构造函数Son.prototype.constructor = Son;  // 子构造函数的constructor手动设置为sonSon.prototype.study = function () {console.log("学习");}var son = new Son('xh', 6, "男")console.log(son);

核心原理:

  • 将子类所共享的方法提取出来,让子类的prototype原型对象 = new 父类()
  • 本质:子类原型对象等于是实例化父类,因为父类实例化后另外开辟空间,就不会影响原来的父类
  • 将子类的constructoe重新指向子类的构造函数
  Son.prototype = new Father() //子构造函数的peototype = new 父构造函数Son.prototype.constructor = Son;  // 子构造函数的constructor手动设置为son

利用原型对象继承方法

es6:继承: extend

  //es6: 类  extendsclass Father1 {constructor(name, age) {this.name = namethis.age = age}work() {console.log("父亲工作");}}class Son1 extends Father1 {constructor(name, age, gender) {super(name, age)this.gender = gender}study() {console.log("子学习");}}var son1 = new Son1("小米", 20, "男")console.log(son1);

es6继承的关键:extend , super

10.对象的特性

  • 封装

将对象所有的组成部分组合起来,尽可能的隐藏对象的部分细节,使其受到保护,只提供有限的接口与外部发生联系。

  • 优点:

    • 安全,使用时无法看到具体的细节,只需要直接调用
    • 便于修改操作
  • 继承

将对象拥有另外一个对象的属性和方法。

父类(基类):被继承的对象。

子类:继承的对象

  • 优点:

    • 提高代码重用性,提高代码的逻辑性和可维护性。

使用es5和es6实现类的封装

  1. es5
  //es5 构造函数+原型对象function Cup(color, size) {this.color = colorthis.size = size}Cup.prototype = {constructor: Cup,save: function () {console.log("储水");},warn: function () {console.log("保温");}}var mycup = new Cup("粉色", "1500ml")
  1. es6
  //es6类 语法糖class Cup1 {constructor(color, size) {this.color = colorthis.size = size}save() {console.log("储水");}warn() {console.log("保温");}}var mycup1 = new Cup("绿色", "500ml")var mycup2 = new Cup1("蓝色", "600ml")

上面这两种完全等同,但es6的更简单,封装更容易

11.函数

函数的三种定义方式

  1. 利用funcation关键字定义函数,也叫命名函数
  //定义,利用funcation 命名函数function fn() {console.log(1);}fn()
  1. 利用字面量定义函数,也叫匿名函数
  //2. 字面量定义  匿名函数var fn1 = function () {console.log(2);}fn1()

由于声明函数方式的不同以及预解析的因素,导致1,2两种方式略微不同。1,这种定义方式,把函数调用提前是完全没有问题的,但2,这种方式就会报错。(预解析知识点)

  1. 实例化Funcation
  //3.实例化Funcationvar fn2 = new Function('num', 'concole.log(num)')fn2(3)

这种方式也是可以传参的,但由于写法复杂,用的并不多。

函数的调用

  1. 普通函数,this指向window
  function fn() {console.log("普通函数");}fn();
  1. 构造函数,this指向实例化的对象
  function Cup(size) {this.size = size}var cup = new Cup("500ml")
  1. 原型对象的方法,this指向实例化的对象
  Cup.prototype = {constructor: Cup,save: function () {console.log("储水");}}var cup = new Cup("500ml")cup.save();
  1. 事件处理函数,this指向事件源 < button >< /button >
  var btn = document.querySelector("button")btn.onclick = function () {console.log("事件处理函数");console.log(this);}
  1. 定时器函数,this 指向window
  setTimeout(function () {console.log("定时器中的函数");}, 1000)
  1. 立即执行函数,this 指向window
    (function () {console.log("立即执行函数");})()

改变this指向的三种方式

call方法

  1. 调用函数
  2. 改变this指向
fn.call(thisAry,arg1,arg2,...)
  • thisAry:当前调用函数this的指向对象
  • arg1,arg2:传递的其他参数

返回值就是函数的返回值

  var obj = { name: "zs", age: 20 }function fn(num) {console.log(1);   20console.log(this);  21console.log(num);   22}fn(0);  25fn.call(obj, 'call')   28

很明显可以看到又调用了 一次函数。而且this指向也变成了obj,不再是window了

apply方法

  1. 调用函数
  2. 改变this指向
fun.apply(thisAry,[arg1,arg2])
  • thisAry:在fun函数运行时指定的this值
  • arg1,arg2 :传递的其他参数

返回值就是函数的返回值

  var obj = { name: "zs", age: 20 }function fn(num) {console.log(1);   20console.log(this);  21console.log(num);   22}fn(0);  25fn.apply(obj, ['apply'])  31

和call方法一样,也会调用函数

也可以不改变参数只传值,不常用。

  fn.apply(null, ['apply'])

bind方法

用到比较多

  1. 改变this指向
fun.bind(thisArg,arg1,arg2,...)
  • thisArg:在fun函数运行时指向的this值
  • arg1,arg2:传递的参数

返回由原来函数改变this之后的新函数

  var obj = { name: "zs", age: 20 }function fn(num) {console.log(1);   20console.log(this);  21console.log(num);   22}fn(0);  25var f = fn.bind(obj, "bind") 33fn()  34

总结

是否可以改变this指向 是否可以调用函数 返回值 使用场景
call 就是函数返回值 用来继承
apply 就是函数返回值 数组相关
bind 返回由原函数改变this之后的新函数 不希望函数立即执行(比如定时器)

原型,构造函数,实例,以及原型链

原型,构造函数,实例三者之间的关系

JavaScript原型链(重要)相关推荐

  1. javascript原型链中 this 的指向

    为了弄清楚Javascript原型链中的this指向问题,我写了个代码来测试: var d = {d: 40};var a = {x: 10,calculate: function (z) {retu ...

  2. 深度解析JavaScript原型链

    深度解析JavaScript原型链 文章目录 深度解析JavaScript原型链 前言 JavaScript原型链,这里只分享我自己的见解 一.原型链是什么 二.心得 三图解 总结 前言 JavaSc ...

  3. JavaScript原型链污染攻击

    前言 最近在看js的时候看到p神的一篇关于js原型链污染的文章,学习一下. 下面转自p神:深入理解 JavaScript Prototype 污染攻击 还有一篇案例关于js原型链污染的ctf题:从一道 ...

  4. JavaScript 原型链和继承面试题

    JavaScript 原型链和继承问题 JavaScript 中没有类的概念的,主要通过原型链来实现继承.通常情况下,继承意味着复制操作,然而 JavaScript默认并不会复制对象的属性,相反,Ja ...

  5. JavaScript 原型链常用方法

    JavaScript 原型链常用方法 对象属性类型 数据属性 Configurable(表示能否通过 delete 删除属性从而重新定义属性,能否修改属性的特性,或者能否把属性修改为访问器属性) En ...

  6. 技术分享经典 javaScript原型链面试题

    技术分享 javaScript原型链 一个小题目 前置知识 变量提升和函数提升 this指针的指向 原型链是什么 new操作符的工资流程 一个小题目 今天我们部门的技术分享上出现了这样一段代码: fu ...

  7. 如何理解JavaScript原型链

    如何理解JavaScript原型链 实例对象与原型对象的关系 构造函数.原型对象和实例对象之间的关系 原型链结构图 函数在原型链中的结构 原型链的理解和总结 实例对象与原型对象的关系 构造函数.原型对 ...

  8. JavaScript原型链以及Object,Function之间的关系

    JavaScript里任何东西都是对象,任何一个对象内部都有另一个对象叫__proto__,即原型,它可以包含任何东西让对象继承.当然__proto__本身也是一个对象,它自己也有自己的__proto ...

  9. 理解JavaScript原型链

    JavaScript中的每个对象都有一个prototype属性,我们称之为原型,而原型的值也是一个对象,因此它也有自己的原型,这样就串联起来了一条原型链,原型链的链头是object,它的prototy ...

  10. JavaScript原型链的理解

    一.原型链的概念 JavaScript是一门面向对象的编程语言,JavaScript 中的所有事物都是对象,并且对象与对象之间不是彼此独立的,而是有"继承"关系的. 这种" ...

最新文章

  1. Spark、Flink、CarbonData技术实践最佳案例解析
  2. continue和break的区别
  3. 设备驱动--中断开关执行的匹配
  4. RNN以及LSTM的介绍和公式梳理
  5. java 成员变量声明顺序_C++核心准则讨论:按照成员声明的顺序定义和初始化成员变量...
  6. workflow and email in QD3 - IS_INBOX_USER method
  7. mysql怎么访问用户B_MySQL访问控制和用户管理
  8. iframe异步加载_5种延迟加载图像的方法以帮助你提升网站性能与用户体验
  9. mysql 指令没有用_Mysql指令
  10. C++ 语法概括总结
  11. 计算机学生的高职英语课程,高职计算机英语课程教学方法探索
  12. 科学管理之父——泰勒的故事
  13. 数学|如何求解线性方程系数?
  14. 报错org.apache.ibatis.builder.BuilderException: Error creating SqlSource for SqlProvider. Method ‘inse
  15. Xcode6中如何添加pch文件
  16. Word2013使用 插入题注的方式为word自带编辑器编辑的公式进行编号
  17. 彩信数据库mmssms.db
  18. 自学java面向实习从零开始路线
  19. 老牌CRM厂商,轻松玩转SaaS!
  20. OpenWRT实现NAT64/DNS64

热门文章

  1. 【JAVA】读取excel导入数据库,形成树状结构
  2. 最大团算法(Maximum Clique)
  3. 10分钟完成蓝牙模块与手机之间的数据读写交互
  4. 安装Office2016,桌面没有PPT图标,右键新建没有图标
  5. python计算菜单消费总额字典_三、Python的列表、字典、元组合集合
  6. 65、Spark Streaming:数据接收原理剖析与源码分析
  7. 百年前的小学课本令人汗颜!
  8. css实现带小三角形的边框
  9. visualsvn php,windowns下使用TortoiseSVN与VisualSVN Server搭建SVN版本控制系统
  10. 八年级计算机考操作试题,初二信息技术考试试题及答案