目录

  • 1. 创建对象的三种方式
    • 1.1 用字面量创建
    • 1.2 用new关键字创建
    • 1.3 借用构造函数创建
  • 2. 实例成员和静态成员
    • 2.1 实例成员
    • 2.2 静态成员
  • 3 构造函数原型
  • 4 对象原型 __ proto__
  • 5 constructor 构造函数
  • 6 构造函数、实例、原型对象三者关系
  • 7 原型链和成员的查找机制
    • 7.1 原型链
    • 7.2 查找机制
  • 8 原型对象中的this指向
  • 9 扩展内置对象
  • 附 vs code的JavaScript语义检查设置

1. 创建对象的三种方式

1.1 用字面量创建

 var obj = {};

1.2 用new关键字创建

 var obj = new Object();
  • new执行做的四件事情:
  1. 在内存中创建一个新的空对象;
  2. this 指向这个新的对象;
  3. 执行构造函数里面的代码,给这个新对象添加属性和方法;
  4. 返回这个新对象(构造函数里面不需要 return )。

1.3 借用构造函数创建

function Person(name,age){this.name = name;this.age = age;
}
var obj = new Person('zs',12);

2. 实例成员和静态成员

构造函数中的属性方法统称为成员,成员又分为实例成员静态成员

2.1 实例成员

定义:构造函数内部通过this添加的成员,;
比如1.3 构造函数中的Person里面的nameage

注意:实例成员,只能通过实例化的对象来访问

2.2 静态成员

定义:直接在构造函数三身上添加的成员。
例如:

Person.sex = '男';

静态成员,只能通过构造函数来访问。

3 构造函数原型

构造函数方法虽然好用,但是存在浪费内存的问题。

如果希望所有对象使用同一个函数,需要做些什么呢?
答案是构造函数原型prototype
构造函数通过原型分配的函数是所有对象所共享的,这就意味着不用再单独开辟内存空间。

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

因此,我们可以把某些固定的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。

举例说明:

  1. 普通构造函数写法:
function Person(uname, age) {this.uname = uname;this.age = age;this.sing = function() {console.log('会唱歌');}
}
var ldh = new Person('刘德华', 18);
var zxy = new Person('张学友', 19);
ldh.sing();//会唱歌
zxy.sing();//会唱歌
  1. 构造函数原型的写法:
function Person(uname, age) {this.uname = uname;this.age = age;
}
Person.prototype.sing = function() {console.log('会唱歌');
}
var ldh = new Person('刘德华', 18);
var zxy = new Person('张学友', 19);
ldh.sing();//会唱歌
zxy.sing();//会唱歌

这样就实现了方法的共享,所有的实例都可以使用这个方法,不再另行开辟内存空间。

总结:
一般情况下,简单数据类型的公共属性放到构造函数里,复杂数据类型如公共方法放到原型对象上

4 对象原型 __ proto__

对象都有一个属性__proto__ 指向构造函数的prototype原型对象,之所以对象可以使用构造函数prototype原型对象的属性和方法,就是因为对象有__proto__原型存在。
__proto__对象原型和原型对象 prototype 是等价的;
__proto__对象原型的意义就在于为对象的查找机制提供一个方向,或者说一条路线。

方法的查找规则:
首先,,看对象身上是否有该方法,如果有就执行这个对象上的方法,如果没有这个方法,因为有__proto__ 的存在,就去构造函数原型对象prototype上去查找方法。


等价验证:

console.log(ldh.__proto__=== Person.prototype)  // 返回 true

注意:
__proto__ 是一个非标准属性,因此实际开发中,不可以直接用它来赋值等操作,它只是内部指向原型对象 prototype

5 constructor 构造函数

对象原型( __proto__)和构造函数(prototype)原型对象里面都有一个属性 constructor 属性 ,constructor 我们称为构造函数,因为它指回构造函数本身。
constructor 主要用于记录该对象引用于哪个构造函数,它可以让原型对象重新指向原来的构造函数。
一般情况下,对象的方法都在构造函数的原型对象中设置。如果有多个对象的方法,我们可以给原型对象采取对象形式赋值,但是这样就会覆盖构造函数原型对象原来的内容,这样修改后的原型对象 constructor 就不再指向当前构造函数了。此时,我们可以在修改后的原型对象中,添加一个 constructor 指向原来的构造函数。

如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动利用constructor指回原来的构造函数(constructor: Person)。

 function Star(uname, age) {this.uname = uname;this.age = age;}// 很多情况下,我们需要手动的利用constructor 这个属性指回 原来的构造函数Star.prototype = {// 如果我们修改了原来的原型对象,给原型对象赋值的是一个对象,则必须手动的利用constructor指回原来的构造函数constructor: Star, // 手动设置指回原来的构造函数sing: function() {console.log('我会唱歌');},movie: function() {console.log('我会演电影');}
}
var zxy = new Star('张学友', 19);
console.log(zxy)

以上代码运行结果,设置constructor属性如图:

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

6 构造函数、实例、原型对象三者关系

  1. 构造函数的prototype属性指向了构造函数原型对象;
  2. 实例对象是由构造函数创建的,实例对象的__proto__属性指向了构造函数的原型对象
  3. 构造函数的原型对象的constructor属性指向了构造函数,实例对象的原型的constructor属性也指向了构造函数。

7 原型链和成员的查找机制

7.1 原型链

只要是实例对象就有_proto__ 原型(属性),指向的构造函数的原型对象,构造函数的原型对象也是一个对象,也有__proto__属性,这样一层一层往上找就形成了原型链。

Star 原型对象里面的__proto__ 原型指向的是Object.prototype

<script>function Star(uname, age) {this.uname = uname;this.age = age;}Star.prototype.sing = function() {console.log('我会唱歌');}var ldh = new Star('刘德华', 18);// 1、只要是对象就有__proto__,指向原型对象console.log(Star.prototype);// 2、Star原型对象里面的__proto__原型指向的是Object.prototypeconsole.log(Star.prototype.__proto__ === Object.prototype); //返回true// 3、我们Object.prototype原型对象里面的__proto__原型,指向为nullconsole.log(Object.prototype.__proto__);
</script>

7.2 查找机制

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

8 原型对象中的this指向

构造函数中的this和原型对象的this,都指向new出来的实例对象。

function Star(uname, age) {this.uname = uname;this.age = age;
}
var that;
Star.prototype.sing = function() {console.log('我会唱歌');that = this;
}
var ldh = new Star('刘德华', 18);
// 1. 在构造函数中,里面this指向的是对象实例 ldh
console.log(that === ldh);//true
// 2.原型对象函数里面的this 指向的是 实例对象 ldh

9 扩展内置对象

可以通过原型对象,对原来的内置对象的方法进行扩展自定义。比如给数据Array增加自定义求偶数和的功能。

console.log(Array.prototype);// 自定义一个求和的方法Array.prototype.sum = function() {sum = 0;for (var i = 0; i < this.length; i++) {sum += this[i];}return sum;}var arr = [1, 2, 3];console.log(arr.sum());

附 vs code的JavaScript语义检查设置


启用或禁用JavaScript 文件的语义检查,若有jsconfig.json 或 tsconfig.json 文件,将覆盖此设置。

"javascript.implicitProjectConfig.checkJs": true,

若要禁用语义检查,则在js文件里加入// @ts-nocheck注释

VS code 插件市场 https://marketplace.visualstudio.com/vscode


下一篇:JavaScript从入门到放弃 -(二)继承

JavaScript从入门到放弃 - (一)构造函数和原型相关推荐

  1. JavaScript从入门到放弃 -(七)ES6

    目录 1. ES6相关概念 1.1 什么是 ES6 ? 1.2 为什么使用 ES6 ? 2 ES6新增语法 2.1 新增关键字 2.1.1 let 关键字 小结 2.1.2 const 关键字 小结 ...

  2. JavaScript从入门到放弃 -(六)正则表达式

    正则表达式 1. 正则表达式概述 1.1 什么是正则表达式 1.2 正则表达式的特点 2. 正则表达式在JavaScript中的使用 2.1 创建正则表达式 2.1.1 通过调用 RegExp 对象的 ...

  3. JavaScript从入门到放弃 -(五)函数进阶(高级用法)

    目录 1. 函数的定义和调用 1.1 函数定义的3种方式 1.2 函数调用方式(常见的6种) 1.2.1 普通函数的调用 1.2.2 对象中的函数调用 1.2.3 构造函数的调用 1.2.4 DOM元 ...

  4. JavaScript从入门到放弃 -(二)继承

    目录 1. Call() 2.子构造函数继承父构造函数中的属性 3. 借用原型对象继承方法 1. Call() 它的作用是: call()可以调用函数: call()可以修改函数运行时this的指向: ...

  5. JavaScript从入门到放弃 -(四)E5 新增方法

    目录 5. trim方法 6. 对象方法 6.1 Object.keys() 6.1.1 作用 6.1.2 语法 6.2 Object.defineProperty() 6.2.1 作用 6.2.2 ...

  6. JavaScript从入门到放弃 -(三)ES5新增方法及商品查询案例

    目录 1. ES5新增方法概述 2. 数组方法 2.1 forEach方法 2.2 filter 筛选数组方法 2.3 some方法 3. 查询商品案例 3.1 HTML结构和CSS样式 3.2 准备 ...

  7. JavaScript从入门到放弃到精通

    JavaScript从入门到放弃 1.什么是JS 是一种流行的脚本语言, Java和JS没有什么关系 1.2环境 1.3调试 运行html 控制台调试 console.log()变量打印输出 断点 2 ...

  8. JavaScript从入门到放弃 - ES6中的对象和类

    重点讲解Tab栏切换.增.删.改 1. 面向过程与面向对象 2.ES6 中的对象与类 2.1 对象 2.2 类 2.2.1 创建类 2.2.1.1 语法 2.2.1.2 实例 2.2.2 类创建添加属 ...

  9. JavaScript从入门到放弃-JavaScript历史介绍

    JavaScript历史 要了解JavaScript,我们首先要回顾一下JavaScript的诞生. 在上个世纪的1995年,当时的网景公司正凭借其Navigator浏览器成为Web时代开启时最著名的 ...

最新文章

  1. 你应该知道的模型评估的五个方法
  2. Android Telephony分析(二) ---- RegistrantList详解
  3. linux集群管理平台,基于Linux平台的高可用集群管理系统的研究与实现
  4. java替换html特殊字符,HTML特殊字符替换问题 html escape相关
  5. Android 图片异步加载的体会,SoftReference已经不再适用
  6. Java实训项目12:GUI学生信息管理系统 - 实现步骤 - 创建服务接口实现类
  7. Flink 合流水位线图解
  8. asp.net core 系列 3 依赖注入服务
  9. 《数据结构导论》之树
  10. caffe+报错︱深度学习参数调优杂记+caffe训练时的问题+dropout/batch Normalization
  11. MFC简易RTF编辑器
  12. Android 在现有项目中引入Compose
  13. 【网络特效】12 个炫酷背景特效库
  14. 全国 省市区 经纬度 (XML格式)
  15. Unity常用旋转方法
  16. npm 和 cnpm 的区别
  17. 《HyVulDect: A hybrid semantic vulnerability mining system based ongraph neural network》阅读笔记
  18. linux网络编程--网络编程的基本函数介绍与使用
  19. 留数定理 含 数学物理方法(吴崇试 第三版)答案详解
  20. 青岛海尔供应商java面试_海尔集团软件工程师面试经验

热门文章

  1. Catalan数应用
  2. 数据结构实验之查找一:二叉排序树
  3. 这样才是代码管理和 Commit 的正确姿势 | 研发效能提升36计
  4. 如何基于Dataphin实现敏感数据保护
  5. 技术干货|基于Apache Hudi 的CDC数据入湖「内附干货PPT下载渠道」
  6. DevOps 能力提升模型
  7. 企业上云如何对SLS日志审计服务进行权限控制
  8. 如何将实时计算 Flink 与自身环境打通
  9. 10个一行代码就能搞定的编程技巧
  10. 新基建带来新机遇!大数据产业发展需“四驱”推动