<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body></body>
<script>
// 对象可以通过函数来创建 → 对象都是通过函数来创建的
// 为了与普通函数区别,构造函数名字的第一个字母通常大写
function Fn() {
// 为了保证构造函数必须与new命令一起使用,一个解决办法是,构造函数内部使用严格模式,即第一行加上use strict。
// 这样的话,一旦忘了使用new命令,直接调用构造函数就会报错。
'use strict'
this.name = '王军'
this.year = '1996'
}
// prototype的属性值是一个对象(属性的集合,再次强调!),默认的只有一个叫做constructor的属性,指向这个函数本身
Fn.prototype.age = 22
Fn.prototype.fnn = function() {
return 2019
}
// 实例化对象 new 命令的作用,就是执行构造函数,返回一个实例对象。
// new 命令的原理
// 使用new命令时,它后面的函数依次执行下面的步骤。
// 创建一个空对象,作为将要返回的对象实例。
// 将这个空对象的原型,指向构造函数的prototype属性。
// 将这个空对象赋值给函数内部的this关键字。
// 开始执行构造函数内部的代码。
// 也就是说,构造函数内部,this指的是一个新生成的空对象,所有针对this的操作,都会发生在这个空对象上。构造函数之所以叫“构造函数”,
// 就是说这个函数的目的,就是操作一个空对象(即this对象),将其“构造”为需要的样子。
let f1 = new Fn()
console.log(f1.name, f1.age, f1.fnn()) // → 王军 22 2019
// 箭头函数不能使用构造函数
// 原因 → 箭头函数没有 this/super/arguments/new.target 的绑定,这些值是由外围最近一层非箭头函数决定
let Fn1 = () => {
this.name = '王军'
this.year = '1996'
}
let f11 = new Fn1()
console.log(f11.name) // 报错 → Uncaught TypeError: fn is not a constructor
</script>
</html>