原型对象prototype的推导过程 和 安全类

原型prototype的推导过程:

初始状态:

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
		// 定义构造函数
		function People(name, age, sex) {
			this.name = name;
			this.age = age;
			this.sex = sex;
			// 此时sayHello的赋值是一个函数, 也就是说,当函数执行的时候, 每一次都在定义一个函数,
			// 函数的功能是一致的, 但是函数的地址不是同一个。 
			this.sayHello = function () {
				console.log("我的名字叫做" + this.name);
			};
		}
		// 初始化两个对象
		var xiaoming = new People("小明", 12, "男");
		var xiaohong = new People("小红", 12, "女");

		console.log(xiaoming.sayHello === xiaohong.sayHello);
	</script>
</body>
</html>

改造一: 将构造函数中的方法提取出来

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
		// 定义构造函数
		function People(name, age, sex) {
			this.name = name;
			this.age = age;
			this.sex = sex;
			// 函数的功能是一致的, 函数的地址同一个。
			this.sayHello = sayHello;
		}

		// 改造1: 将函数提取出来
		function sayHello() {
			console.log("我的名字叫做" + this.name);
		}
		// 初始化两个对象
		var xiaoming = new People("小明", 12, "男");
		var xiaohong = new People("小红", 12, "女");

		console.log(xiaoming.sayHello === xiaohong.sayHello);
	</script>
</body>
</html>

改造二:要是多种方法,还得定义很多全局方法,则将所有方法放在一个对象中,是全局变量压缩为一个

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
		// 定义构造函数
		function People(name, age, sex) {
			this.name = name;
			this.age = age;
			this.sex = sex;
			// 函数的功能是一致的, 函数的地址是同一个。
			this.sayHello = obj.sayHello;
			this.say = obj.say;
			this.haha = obj.haha;
		}

		// 改造2: 将所有方法放在一个对象中,是全局变量压缩为一个
		var obj = {
			sayHello: function () {
				console.log("我的名字叫做" + this.name);
			},
			say:function () {
				console.log("wawawawawawaw")
			},
			haha:function () {
				console.log("hahahahaha")
			}
		}

		// 初始化两个对象
		var xiaoming = new People("小明", 12, "男");
		var xiaohong = new People("小红", 12, "女");

		console.log(xiaoming.sayHello === xiaohong.sayHello);
	</script>
</body>
</html>

改造三:虽然全局变量压缩成一个了,但是这一个也可以被省去

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
		// 改造3: 之前改造2确实将全局变量压缩为一个了, 但是这一个对象也不可以存在。
		// 定义构造函数
		function People(name, age, sex) {
			this.name = name;
			this.age = age;
			this.sex = sex; 
			// 函数的功能是一致的, 函数的地址是同一个。
			this.sayHello = People.obj.sayHello;
			this.say = People.obj.say;
			this.haha = People.obj.haha;
		}

		// 改造2: 将所有方法放在一个对象中,是全局变量压缩为一个
		People.obj = {
			sayHello: function () {
				console.log("我的名字叫做" + this.name);
			},
			say:function () {
				console.log("wawawawawawaw")
			},
			haha:function () {
				console.log("hahahahaha")
			}
		}

		// 初始化两个对象
		var xiaoming = new People("小明", 12, "男");
		var xiaohong = new People("小红", 12, "女");

		console.log(xiaoming.sayHello === xiaohong.sayHello);
	</script>
</body>
</html>

原型的“诞生”:

    构造函数提供了一个prototype原型对象,这个原型对象是每一个函数都拥有的属性

    原型对象上的东西可以被实例化的实例共享

    原型的作用:共享方法

    以后给构造函数添加方法一定写在原型对象上添加

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
        // 定义构造函数
	function People(name, age, sex) {
		this.name = name;
		this.age = age;
		this.sex = sex;
	}

	// 其实布兰达艾奇,早就考虑到了这一点, 为我们提供了一个People.prototype, 意思就是 原型 它是每一个函数都拥有的属性, 指向一个对象, 原型上面的东西, 可以被实例化的对象共享。
	
	People.prototype.sayHello = function() {
		console.log("我的名字叫" + this.name);
	}

	// 初始化两个对象
	var xiaoming = new People("小明", 12, "男");
	var xiaohong = new People("小红", 12, "女");
	xiaoming.sayHello();
	xiaohong.sayHello();
	console.log(xiaoming.sayHello === xiaohong.sayHello);

	// 原型的作用: 实例共享方法
	// 以后给构造函数添加方法, 一定要写在原型上面。
	</script>
</body>
</html>

安全类

定义: 无论如何调用类,总是返回类的实例。gouzao

解决问题: 有些程序员,在调用构造函数的时候,不使用new关键字,所以导致代码出问题。

    构造函数中:this 指向的是 实例对象

    普通函数中:this指向的是 window

拓展知识点:

    一个普通函数 没有返回值或者没有return 用一个变量接收,输出变量值为undefined

<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<title>Document</title>
</head>
<body>
	<script type="text/javascript">
	// 创建对象三种方式 字面量  构造函数  直接object()
	// var obj = {};
	// var obj1 = new Object();
	// var obj2 = Object();
	// console.log(obj, obj1, obj2)



	// function People(name, age, sex) {
	// 	this.name = name;
	// 	this.age = age;
	// 	this.sex = sex;
	// }

	// // 实例化
	// // var p = new People("小红", 12, "男");
	// var p1 = People("小明", 12, "男");

	/*
	 * 拓展知识点:输出p1 是 undefined
	 * 一个普通函数 没有返回值或者没有return 用一个变量接受,变量值为undefined
	 */


	//  此时, 当使用new 调用People时候, 一切正常。
	//  但是,当做普通函数执行的时候, 将函数内部的this指向了window, 所以讲所有属添加给了window
	//  这个时候,这个类就不是安全类。



	// 我们要改造成为安全类

	// 分析: 当时用new调用时候, 内部的this是People的实例
	// 当做普通函数执行的时候后, 内部的this指向了window
	function People(name, age, sex) {
		// console.log(this)
		// 利用this指向来记性判断
		if (this === window) {
			// 说明当做了普通函数执行了, 普通函数要想返回内容 需要return;
			return new People(name, age, sex);
		} else {
			// 说明正常调用 一切照旧
			this.name = name;
			this.age = age;
			this.sex = sex;
		}
	}

	var p = new People();
	var p1 = People();


	// 安全类: 无论是如何调用函数, 都可以返回函数的实例化对象。
	</script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值