JavaScript从入门到放弃 - (一)构造函数和原型
目录
- 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
执行做的四件事情:
- 在内存中创建一个新的空对象;
- 让
this
指向这个新的对象; - 执行构造函数里面的代码,给这个新对象添加属性和方法;
- 返回这个新对象(构造函数里面不需要
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
里面的name
、age
。
注意:实例成员,只能通过实例化的对象来访问
2.2 静态成员
定义:直接在构造函数三身上添加的成员。
例如:
Person.sex = '男';
静态成员,只能通过构造函数来访问。
3 构造函数原型
构造函数方法虽然好用,但是存在浪费内存的问题。
如果希望所有对象使用同一个函数,需要做些什么呢?
答案是构造函数原型prototype
构造函数通过原型分配的函数是所有对象所共享的,这就意味着不用再单独开辟内存空间。
JavaScript 规定,每一个构造函数都有一个
prototype
属性,指向另一个对象。这个prototype
就是一个对象,这个对象的所有属性和方法,都会被构造函数所拥有。
因此,我们可以把某些固定的方法,直接定义在prototype对象上,这样所有对象的实例就可以共享这些方法。
举例说明:
- 普通构造函数写法:
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();//会唱歌
- 构造函数原型的写法:
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 构造函数、实例、原型对象三者关系
- 构造函数的
prototype
属性指向了构造函数原型对象; - 实例对象是由构造函数创建的,实例对象的
__proto__
属性指向了构造函数的原型对象; - 构造函数的原型对象的
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从入门到放弃 - (一)构造函数和原型相关推荐
- JavaScript从入门到放弃 -(七)ES6
目录 1. ES6相关概念 1.1 什么是 ES6 ? 1.2 为什么使用 ES6 ? 2 ES6新增语法 2.1 新增关键字 2.1.1 let 关键字 小结 2.1.2 const 关键字 小结 ...
- JavaScript从入门到放弃 -(六)正则表达式
正则表达式 1. 正则表达式概述 1.1 什么是正则表达式 1.2 正则表达式的特点 2. 正则表达式在JavaScript中的使用 2.1 创建正则表达式 2.1.1 通过调用 RegExp 对象的 ...
- JavaScript从入门到放弃 -(五)函数进阶(高级用法)
目录 1. 函数的定义和调用 1.1 函数定义的3种方式 1.2 函数调用方式(常见的6种) 1.2.1 普通函数的调用 1.2.2 对象中的函数调用 1.2.3 构造函数的调用 1.2.4 DOM元 ...
- JavaScript从入门到放弃 -(二)继承
目录 1. Call() 2.子构造函数继承父构造函数中的属性 3. 借用原型对象继承方法 1. Call() 它的作用是: call()可以调用函数: call()可以修改函数运行时this的指向: ...
- 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 ...
- JavaScript从入门到放弃 -(三)ES5新增方法及商品查询案例
目录 1. ES5新增方法概述 2. 数组方法 2.1 forEach方法 2.2 filter 筛选数组方法 2.3 some方法 3. 查询商品案例 3.1 HTML结构和CSS样式 3.2 准备 ...
- JavaScript从入门到放弃到精通
JavaScript从入门到放弃 1.什么是JS 是一种流行的脚本语言, Java和JS没有什么关系 1.2环境 1.3调试 运行html 控制台调试 console.log()变量打印输出 断点 2 ...
- JavaScript从入门到放弃 - ES6中的对象和类
重点讲解Tab栏切换.增.删.改 1. 面向过程与面向对象 2.ES6 中的对象与类 2.1 对象 2.2 类 2.2.1 创建类 2.2.1.1 语法 2.2.1.2 实例 2.2.2 类创建添加属 ...
- JavaScript从入门到放弃-JavaScript历史介绍
JavaScript历史 要了解JavaScript,我们首先要回顾一下JavaScript的诞生. 在上个世纪的1995年,当时的网景公司正凭借其Navigator浏览器成为Web时代开启时最著名的 ...
最新文章
- 你应该知道的模型评估的五个方法
- Android Telephony分析(二) ---- RegistrantList详解
- linux集群管理平台,基于Linux平台的高可用集群管理系统的研究与实现
- java替换html特殊字符,HTML特殊字符替换问题 html escape相关
- Android 图片异步加载的体会,SoftReference已经不再适用
- Java实训项目12:GUI学生信息管理系统 - 实现步骤 - 创建服务接口实现类
- Flink 合流水位线图解
- asp.net core 系列 3 依赖注入服务
- 《数据结构导论》之树
- caffe+报错︱深度学习参数调优杂记+caffe训练时的问题+dropout/batch Normalization
- MFC简易RTF编辑器
- Android 在现有项目中引入Compose
- 【网络特效】12 个炫酷背景特效库
- 全国 省市区 经纬度 (XML格式)
- Unity常用旋转方法
- npm 和 cnpm 的区别
- 《HyVulDect: A hybrid semantic vulnerability mining system based ongraph neural network》阅读笔记
- linux网络编程--网络编程的基本函数介绍与使用
- 留数定理 含 数学物理方法(吴崇试 第三版)答案详解
- 青岛海尔供应商java面试_海尔集团软件工程师面试经验