原型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>