js基础:08、构造函数(共享方法)、原型(prototype)、原型对象、(修改原型)toString方法、垃圾回收

javascript 的构造函数及原型及原型对象:

Ⅰ、构造函数(共享方法):

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			/*
			 * 创建一个 Person 构造函数
			 * 	- 在 Person 构造函数中,为每一个对象都添加了一个 sayName 方法,
			 * 		目前我们的方法是在构造函数内部创建的,
			 * 			也就是构造函数每执行一次就会创建一个新的 sayName 方法
			 * 		也是所有实例的 sayName 都是唯一的。
			 * 		这样就导致了构造函数执行一次就会创建一个新的方法,
			 * 			执行 10000 次就会创建 10000 个新的方法,而 10000 个方法都是一摸一样的
			 * 			这是完全没有必要,完全可以使所有的对象共享同一个方法
			 */
			function Person(name , age , gender){
				this.name = name;
				this.age = age;
				this.gender = gender;
				//向对象中添加一个方法
				//this.sayName = fun;
			}
			



			//将 sayName 方法在全局作用域中定义
			/*
			 * 将函数定义在全局作用域,污染了全局作用域的命名空间
			 * 	而且定义在全局作用域中也很不安全
			 */
			/*function fun(){
				alert("Hello大家好,我是:"+this.name);
			};*/




			//向原型中添加 sayName 方法
			Person.prototype.sayName = function(){
				alert("Hello大家好,我是:"+this.name);
			};
			
			//创建一个 Person 的实例
			var per = new Person("孙悟空",18,"男");
			var per2 = new Person("猪八戒",28,"男");
			per.sayName();// Hello大家好,我是:孙悟空
			per2.sayName();// Hello大家好,我是:猪八戒
			
			console.log(per.sayName == per2.sayName);// true
			
			
		</script>
	</head>
	<body>
	</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

Ⅱ、原型(prototype):

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			/*
			 * 原型 prototype
			 * 
			 * 	我们所创建的每一个函数,解析器都会向函数中添加一个属性 prototype
			 * 		这个属性对应着一个对象,这个对象就是我们所谓的原型对象
			 * 	如果函数作为普通函数调用 prototype 没有任何作用
			 * 	当函数以构造函数的形式调用时,它所创建的对象中都会有一个隐含的属性,
			 * 		指向该构造函数的原型对象,我们可以通过 __proto__ 来访问该属性
			 * 
			 * 	原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象,
			 * 		我们可以将对象中共有的内容,统一设置到原型对象中。
			 * 
			 * 当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,
			 * 	如果没有则会去原型对象中寻找,如果找到则直接使用
			 * 
			 * 以后我们创建构造函数时,可以将这些对象共有的属性和方法,统一添加到构造函数的原型对象中,
			 * 	这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这些属性和方法了
			 */
			
			function MyClass(){
				
			}
			

			//向 MyClass 的原型中添加属性 a
			MyClass.prototype.a = 123;
			

			//向 MyClass 的原型中添加一个方法
			MyClass.prototype.sayHello = function(){
				alert("hello");
			};
			
			var mc = new MyClass();
			var mc2 = new MyClass();
			
			// console.log(MyClass.prototype);// {a: 123, sayHello: ƒ}(即:MyClass 指向的原型对象 Object)
			// console.log(mc2.__proto__ == MyClass.prototype);// true
			

			//向 mc 中添加 a 属性
			mc.a = "我是mc中的a";
			
			console.log(mc2.a);// 123(因为:mc 上虽添加了 a 属性值,但 mc2 上并没有 a 属性值,因此此时的 a 是原型对象上的值)
			mc.sayHello();
			
			
		</script>
	</head>
	<body>
	</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

Ⅲ、原型对象:

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			
			/*
			 * 创建一个构造函数
			 */
			function MyClass(){
				
			}
			
			//向 MyClass 的原型中添加一个 name 属性
			MyClass.prototype.name = "我是原型中的名字";
			
			var mc = new MyClass();
			mc.age = 18;
			
			// console.log(mc.name);// 我是原型中的名字
			


			//使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有,也会返回 true
			// console.log("name" in mc);// true
			// console.log("hasOwnProperty" in mc);// true
			


			//可以使用对象的 hasOwnProperty() 来检查对象自身中是否含有该属性
			//使用该方法只有当对象自身中含有属性时,才会返回 true
			// console.log(mc.hasOwnProperty("age"));// true(说明:age 是 mc 自己的属性值)
			// console.log(mc.hasOwnProperty("name"));// false(综上 in 用法说明:name 是 mac 原型对象上的属性值,不是 mc 自己的属性值)
			
			// console.log(mc.hasOwnProperty("hasOwnProperty"));// false(综上 in 用法说明:hasOwnProperty 是 mac 原型对象上的属性值,不是 mc 自己的属性值)
			



			/*
			 * 原型对象也是对象,所以它也有原型,
			 * 	当我们使用一个对象的属性或方法时,会先在自身中寻找,
			 * 		自身中如果有,则直接使用,
			 * 		如果没有则去原型对象中寻找,如果原型对象中有,则使用,
			 * 		如果没有则去原型的原型中寻找,直到找到 Object 对象的原型,
			 * 		Object 对象的原型没有原型,如果在 Object 原型中依然没有找到,则返回 undefined
			 */
			
			console.log(mc.__proto__.hasOwnProperty("hasOwnProperty"));//false(说明:mc 原型对象上没有 hasOwnProperty 属性值,即:hasOwnProperty 不是 mc 原型对象自己的属性值)
			
			console.log(mc.__proto__.__proto__.hasOwnProperty("hasOwnProperty"));//true(说明:mc 原型对象的原型对象上有 hasOwnProperty 属性值,即:hasOwnProperty 是 mc 原型对象的原型对象自己的属性值 )
			
			console.log(mc.__proto__.__proto__.__proto__);// null(即:Object 的原型为 null)
			
			console.log(mc.hello);// undefined(即:在 Object 原型中依然没有找到,返回值为 undefined)
			
			console.log(mc.__proto__.__proto__.__proto__)//null(即:Object 的原型为 null)
			
		</script>
	</head>
	<body>
	</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

Ⅳ、修改toString方法:

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			
			function Person(name , age , gender){
				this.name = name;
				this.age = age;
				this.gender = gender;
			}
			
			//修改 Person 原型的 toString 方法:
			Person.prototype.toString = function(){
				return "Person[name1="+this.name+",age="+this.age+",gender="+this.gender+"]";
			};
			
			
			//创建一个 Person 实例
			var per = new Person("孙悟空",18,"男");
			var per2 = new Person("猪八戒",28,"男");
			



			//当我们直接在页面中打印一个对象时,事件上是输出的对象的 toString() 方法的返回值
			//如果我们希望在输出对象(即:调用 toString() 方法的返回值)时不输出 [object Object],可以为对象添加一个 toString() 方法
			// Person[name=孙悟空,age=18,gender=男]
			per.toString = function(){
				return "Person[name2="+this.name+",age="+this.age+",gender="+this.gender+"]";
			};
			

			var result = per.toString();
			console.log("result = " + result);// result = Person[name2=孙悟空,age=18,gender=男]
			// (说明:per 自身有 toString 方法就调用自身的,没有就调用 per 原型对象上的 toString 方法,没有就调用 per 原型对象的原型对象上(即:应该是 Object 原型对象)的 toString 方法)
			console.log(per.__proto__.__proto__.hasOwnProperty("toString"));// true(说明:toString 方法应该是 Object 原型对象上的属性方法)
			console.log(per.__proto__.__proto__.__proto__);// null(说明:toString 就是原型对象 Object 上的属性方法)
			console.log(per2);// Person {name: '猪八戒', age: 28, gender: '男'}
			console.log(per);// Person {name: '孙悟空', age: 18, gender: '男', toString: ƒ}
			
			
		</script>
	</head>
	<body>
	</body>
</html>

其二、结果为:

// 一进入页面后的控制台:

Ⅴ、垃圾回收(对象篇):

其一、代码为:

html 复制代码
<!DOCTYPE html>
<html>
	<head>
		<meta charset="UTF-8">
		<title></title>
		<script type="text/javascript">
			/*
			 * 垃圾回收(GC)
			 * 	- 就像人生活的时间长了会产生垃圾一样,程序运行过程中也会产生垃圾
			 * 		这些垃圾积攒过多以后,会导致程序运行的速度过慢,
			 * 		所以我们需要一个垃圾回收的机制,来处理程序运行过程中产生垃圾
			 *  - 当一个对象没有任何的变量或属性对它进行引用,此时我们将永远无法操作该对象,
			 * 		此时这种对象就是一个垃圾,这种对象过多会占用大量的内存空间,导致程序运行变慢,
			 * 		所以这种垃圾必须进行清理。
			 * 	- 在 JS 中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁,
			 * 		我们不需要也不能进行垃圾回收的操作
			 * 	- 我们需要做的只是要将不再使用的对象设置 null 即可
			 * 
			 */
			var obj = new Object();
			
			//对对象进行各种操作。。。。
			
			
			obj = null;
			
			
			
		</script>
	</head>
	<body>
	</body>
</html>

其二、结果为:

// 一进入页面后的控制台(只要运行不报错就没有问题):

Ⅵ、小结:

其一、哪里有不对或不合适的地方,还请大佬们多多指点和交流!
其二、若有转发或引用本文章内容,请注明本博客地址(直接点击下面 url 跳转) https://blog.csdn.net/weixin_43405300,创作不易,且行且珍惜!
其三、有兴趣的话,可以多多关注这个专栏(Vue(Vue2+Vue3)面试必备专栏)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_11525646.html?spm=1001.2014.3001.5482
其四、再有兴趣的话,也可以多多关注这个专栏(Java)(直接点击下面 url 跳转):https://blog.csdn.net/weixin_43405300/category_12654744.html?spm=1001.2014.3001.5482

相关推荐
代码搬运媛1 小时前
Jest 测试框架详解与实现指南
前端
天竺鼠不该去劝架2 小时前
金融行业 AI Agent 落地架构 存量银行系统适配改造方案
经验分享
counterxing2 小时前
我把 Codex 里的 Skills 做成了一个 MCP,还支持分享
前端·agent·ai编程
wangqiaowq2 小时前
windows下nginx的安装
linux·服务器·前端
之歆2 小时前
DAY_12JavaScript DOM 完全指南(二):实战与性能篇
开发语言·前端·javascript·ecmascript
发现一只大呆瓜2 小时前
Vite凭什么这么快?3分钟带你彻底搞懂 Vite 热更新的幕后黑手
前端·面试·vite
Maimai108083 小时前
React如何用 @microsoft/fetch-event-source 落地 SSE:比原生 EventSource 更灵活的实时推送方案
前端·javascript·react.js·microsoft·前端框架·reactjs·webassembly
candyTong3 小时前
Claude Code 的 Edit 工具是怎么工作的
javascript·后端·架构
weixin_537217064 小时前
答辩ppt模板资源合集
经验分享
kyriewen4 小时前
产品经理把PRD写成“天书”,我用AI半小时重写了一遍,他当场愣住
前端·ai编程·cursor