技术分享
首页
  • JavaScript

    • 构造函数和原型
    • Cookie和Session
    • Object.create(null)和{}
    • TypeScript配置
    • typescript入门到进阶
  • 框架

    • Vue-Router
    • React基础入门
  • 其它

    • Http协议
    • 跨域问题总结
  • 分析Promise实现
  • Axios源码分析
  • Webpack原理
  • vueRouter源码分析
  • Vue

    • Vite快速搭建Vue3+TypeScript项目
    • Cordova打包Vue项目的问题
    • Vue将汉字转为拼音,取出首字母
  • JavaScript

    • new Function
  • 后端

    • Node.js中使用Crypto生成Token
    • Body-Parser处理多层对象的问题
  • 其它

    • 项目Demo汇总
    • Vuepress+Vercel搭建个人站点
    • 项目中能用到的
    • husky规范代码提交
  • Mongoose基础
  • Multer文件上传中间件的使用
  • JavaScript

    • 浅谈两数全等
    • JavaScript进制转换
    • 手写bind,apply,call和new
  • 算法

    • 数组去重和排序
    • 数组扁平化
    • 斐波那契数列
  • JavaScript 数据结构
  • 其它

    • webpack面试题
    • vite面试题
    • svg和canvas的优缺点
    • TypeScript面试题
    • Vue常见面试题
  • 计算机网络

    • 数据链路层
    • 网络层
  • Git的使用
  • Nginx的使用
  • CentOS7安装Nginx
  • 正则表达式
  • SEO搜索引擎优化
  • Serverless介绍
友链
GitHub (opens new window)

鑫生活

总有人要赢,为什么不能是我
首页
  • JavaScript

    • 构造函数和原型
    • Cookie和Session
    • Object.create(null)和{}
    • TypeScript配置
    • typescript入门到进阶
  • 框架

    • Vue-Router
    • React基础入门
  • 其它

    • Http协议
    • 跨域问题总结
  • 分析Promise实现
  • Axios源码分析
  • Webpack原理
  • vueRouter源码分析
  • Vue

    • Vite快速搭建Vue3+TypeScript项目
    • Cordova打包Vue项目的问题
    • Vue将汉字转为拼音,取出首字母
  • JavaScript

    • new Function
  • 后端

    • Node.js中使用Crypto生成Token
    • Body-Parser处理多层对象的问题
  • 其它

    • 项目Demo汇总
    • Vuepress+Vercel搭建个人站点
    • 项目中能用到的
    • husky规范代码提交
  • Mongoose基础
  • Multer文件上传中间件的使用
  • JavaScript

    • 浅谈两数全等
    • JavaScript进制转换
    • 手写bind,apply,call和new
  • 算法

    • 数组去重和排序
    • 数组扁平化
    • 斐波那契数列
  • JavaScript 数据结构
  • 其它

    • webpack面试题
    • vite面试题
    • svg和canvas的优缺点
    • TypeScript面试题
    • Vue常见面试题
  • 计算机网络

    • 数据链路层
    • 网络层
  • Git的使用
  • Nginx的使用
  • CentOS7安装Nginx
  • 正则表达式
  • SEO搜索引擎优化
  • Serverless介绍
友链
GitHub (opens new window)
  • js基础
  • vue入门
  • react基础入门
  • http协议
  • cookie和session
  • 跨域问题总结
  • 构造函数和原型
    • 构造函数
      • 特点
      • new 在执行时会做四件事情:
    • 原型
      • 继承
      • call
      • apply
      • bind
    • 类
      • 本质
      • 特点
  • Object.create(null)和{}
  • TypeScript配置
  • Vue-Router
  • typescript入门到进阶
  • 前端
coderly
2019-08-17

构造函数和原型

# 构造函数和原型

创建对象可以通过以下三种方式

  1. 对象字面量
var obj = {}
1
  1. new Object()
var obj = new Object()
1
  1. 自定义构造函数

# 构造函数

构造函数是一种特殊的函数,主要用来初始化对象,即为对象成员变量赋初始值,它总与 new 一起使用。我们可以把对象中一些公共的属性和方法抽取出来,然后封装到这个函数里面;

# 特点

  1. 构造函数有原型对象 prototype;
  2. 构造函数原型对象 prototype 里面有 constructor 指向构造函数本身;
  3. 构造函数可以通过原型对象添加方法;
  4. 构造函数创建的实例对象有proto原型指向构造函数的原型对象;

# new 在执行时会做四件事情:

  1. 在内存中创建一个新的对象;
  2. 让 this 指向这个新的对象;
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法;
  4. 饭后这个新对象(所以构造函数里面不需要 return)

JavaScript 构造函数中可以添加一些成员,可以在构造函数本身上添加,也可以在构造函数内部的 this 上添加。通过这两种方式添加的成员,就分别称为静态成员和实例成员

  1. 静态成员:在构造函数上添加的成员称为静态成员,只能由构造函数本身来访问。
  2. 实例成员:在构造函数内部创建的对象成员称为实例成员,只能由实例化的对象来访问。实例成员就是构造函数内部通过 this 添加的成员;

# 原型

  1. 构造函数通过原型分配的函数是所有对象所共享的
  2. JavaScript 规定,每一个构造函数都有一个 prototype 属性,指向另一个对象。注意这个 prototype 就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
  3. 我们可以把那些不变的方法,直接定义在 prototype 对象上,这样所有对象的实例就可以共享这些方法。

# 继承

ES6 之前并没有我们提供 extends 继承。我们可以通过构造函数+原型对象模拟实现继承,被称为组合继承

# call

调用这个函数,并且修改函数运行时的 this 指向

fun.call(thisArg, arg1, arg2, ...)
1

# apply

fun.apply(thisArg, [array])
1

# 主要应用

比如说,我们可以利用 apply 借助于数学内置对象求最大值;

var arr = [1, 23, 43, 12, 4, 11]
Math.max.apply(null, arr)
1
2

# bind

不会调用函数。但是能改变内部 this 指向;

fun.bind(thisArg, arr1, arr2 , ...)
1
  1. thisArg:在 fun 函数运行时指定的 this 值;
  2. arg1、arg2:传递的其它参数;
  3. 返回由指定的 this 值和初始化参数改造的原函数拷贝
var o = {
  name: 'coderly',
}
function fn() {
  console.log(this)
}
var f = fn.bind(o)
f()
// 1. 不会调用原来的函数,可以改变原来函数内部的this指向;
// 2. 返回的是原函数改变this之后产生的新函数;
1
2
3
4
5
6
7
8
9
10

# bind 应用

如果有的函数我们不需要立即调用,但是又想改变这个函数内部的 this 指向,此时用 bind

【例子】:我们有一个按钮,当我们点击了之后,就禁用这个按钮,3 秒钟之后开启这个按钮;

var btn = document.querySelector('btn')
btn.onclick = function() {
  this.disabled = true
  setTimeout(
    function() {
      this.disabled = false
    }.bind(this),
    3000
  )
}
1
2
3
4
5
6
7
8
9
10

# 主要应用场景

  1. call 经常做继承;
  2. apply 经常跟数组有关系,比如借助于数学对象实现数组最大值最小值;
  3. bind 不调用函数,但是还想改变 this 指向,比如改变定时器内部的 this 指向;

# 借用构造函数继承父类型属性

核心原理:通过 call()把父类型的 this 指向子类型的 this,这样就可以实现子类型继承父类型的属性;

// 父构造函数
function Father(name, age) {
  this.name = name
  this.age = age
}
Father.prototype.money = function() {
  console.log('我有1000元钱')
}
// 子构造函数
function Son(name, age) {
  // 继承Father内部属性
  Father.call(this, name, age)
}
// 继承Father原型上的方法
// 如果利用对象的形式修改了原型对象,别忘了利用constructor指回原来的原型对象;
Son.prototype = new Father()
Son.prototype.constructor = Son
// Son的自己的方法,必须在上一步之后
Son.prototype.Mine = function() {
  console.log('我私藏了100元钱')
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

【注意】:如果利用对象的形式修改了原型对象,别忘了利用 constructor 指回原来的原型对象;

# 类

# 本质

  1. class 本质还是一个 function;
  2. 类的所有方法都定义在类的 prototype 原型对象;
  3. 类创建的实例,里面也有proto指向类的 prototype 原型对象;
  4. 所以 ES6 的类它的绝大部分功能,ES5 都可以做到,新的 class 写法只是让对象原型的写法更加清晰、更像面向对象编程的语法而已;
  5. 所以 ES6 的类其实就是语法糖;
  6. 语法糖:语法糖就是一种便捷写法,简单理解,有两种方法可以实现桐乡的功能,但是一种写法更加清晰、方便,那么这个方法就是语法糖;

# 特点

  1. 类的本质其实还是一个函数,我们也可以简单的认为,类就是构造函数的另一种写法;
  2. 类有原型对象 prototype;
  3. 类原型对象 prototype 里面有 constructor 指向类本身;
  4. 类可以通过原型对象添加方法;
#JavaScript
上次更新: 2021/09/13, 15:11:59
跨域问题总结
Object.create(null)和{}

← 跨域问题总结 Object.create(null)和{}→

最近更新
01
css
09-13
02
html
09-13
03
README
09-13
更多文章>
Theme by Vdoing | Copyright © 2021-2021 coderly | MIT License
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式