2-14、new
用new操作符调用函数

- 你可能知道new操作符和“面向对象”息息相关,但是现在,我们先不探讨它的“面向对象”意义,而是先把
用new调用函数的执行步骤和它上下文弄清楚
- JS规定,
使用new操作符调用函数会进行“四步走”:
- 函数体内会自动创建出一个空白对象
- 函数的上下文(this)会指向这个对象
- 函数体内的语句会执行
- 函数会返回上下文对象,即使函数没有return语句
四步走详解



- 第4步:函数会自动返回上下文对象,即使函数没有return语句

上下文规则总结

代码案例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>2-14、new</title>
</head>
<body>
<script>
function fun() {
this.a = 3;
this.b = 6;
if (this.a > this.b) {
this.c = 10;
} else {
this.c = 20;
}
}
// 使用new调用函数时,this指代的是秘密创建出的空对象,当被this.a/b/c时往里面添加了属性和属性值,所以这个时候返回的是这个秘密创建的对象
var obj = new fun();
console.log(obj);
</script>
</body>
</html>
2-15、类与实例
类与实例

类好比是“蓝图”
- 如同“蓝图”一样,类只描述对象会拥有哪些属性和方法,但是并不具体指明属性的值


类和实例


构造函数和“类”

- Java、C++等是
“面向对象”(object-oriented)语言
- JavaScript是
“基于对象”(object-based)语言
- JavaScript中的
构造函数可以类比OO语言中的“类”,写法的确类似,但和真正OO语言还是有本质不同,在后续课程还将看见JS和其他OO语言完全不同的、特有的原型特性
3-1、prototype 和原型链查找
什么是prototype
- 任何函数都有
prototype属性,prototype是英语“原型”的意思
- prototype属性值是个对象,它默认拥有
constructor属性指回函数

- 普通函数来说的prototype属性没有任何用处,而
构造函数的prototype属性非常有用
构造函数的prototype属性是它的实例的原型
构造函数的prototype是实例的原型

原型链查找
- JavaScript规定:
实例可以打点访问它的原型的属性和方法,这被称为“原型链查找”



hasOwnProperty
- hasOwnProperty方法可以检查对象是否真正“自己拥有”某属性或者方法

in
- in运算符只能
检查某个属性或方法是否可以被对象访问,不能检查是否是自己的属性或方法

代码案例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3-1、prototype 和原型链查找</title>
</head>
<body>
<script>
function sum(a,b) {
return a+b;
}
// prototype:是一个函数自带的属性,这个代码英文意思是“原型”。prototype的属性值是个对象,它默认拥有constructor属性指回函数
console.log(sum.prototype);
console.log(typeof sum.prototype);
console.log(sum.prototype.constructor === sum);
function People(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 实例化
var xiaoming = new People("小明",12,"男");
// 测试三角关系是否存在
console.log(xiaoming.__proto__ === People.prototype);
function People1(name,age,sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 往原型上添加nationality属性
People1.prototype.nationality = "中国";
// 实例化
var xiaogang = new People1("小刚",13,"男");
var tom = new People1("汤姆",10,"男");
tom.nationality = "美国"; // 原型链的遮蔽效应
console.log(xiaogang.nationality); // 中国
console.log(xiaogang);
console.log(tom.nationality); // 美国
//
console.log(xiaogang.hasOwnProperty("name"));
console.log(xiaogang.hasOwnProperty("sex"));
console.log(xiaogang.hasOwnProperty("age"));
console.log(xiaogang.hasOwnProperty("nationality"));
console.log("name" in xiaogang);
console.log("sex" in xiaogang);
console.log("age"in xiaogang);
console.log("nationality" in xiaogang);
</script>
</body>
</html>
3-2、在prototype上添加方法
之前,我们将方法写到了对象身上


- 把方法直接添加到实例身上的缺点:每个实例和每个实例的方法函数
都是内存中不同的函数,造成了内存的浪费
- 解决办法:
将方法写到prototype上
方法要写到prototype上

代码案例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3-2、在prototype上添加方法</title>
</head>
<body>
<script>
function People() {
this.sayHello = function () { };
};
var xiaoming = new People();
var xiaogang = new People();
var xiaohong = new People();
console.log(xiaoming.sayHello === xiaohong.sayHello);
function People1(name, age, sex) {
this.name = name;
this.age = age;
this.sex = sex;
}
// 要把方法写在原型上,不然会造成内存浪费
People1.prototype.sayHello = function () {
console.log("你好,我是" + this.name + "我今年" + this.age + "岁了");
}
People1.prototype.growup = function () {
this.age++;
}
var xiaoming = new People1("小明",12,"男")
var xiaohong = new People1("小红",11,"女")
console.log(xiaoming.sayHello === xiaohong.sayHello);
xiaoming.sayHello();
xiaohong.sayHello();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.growup();
xiaoming.sayHello();
xiaohong.sayHello();
</script>
</body>
</html>
3-3、原型链的终点
原型链的终点

关于数组的原型链

代码案例
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>3-3、原型链的终点</title>
</head>
<body>
<script>
function People(name,age) {
this.name = name;
this.age = age;
};
var xiaoming = new People("小明",12);
console.log(xiaoming.__proto__.__proto__ === Object.prototype); // turn
console.log(Object.prototype.__proto__); // null
// var char = xiaoming.toString();
// console.log(char);
console.log(Object.prototype.hasOwnProperty("hasOwnProperty")); // true
console.log(Object.prototype.hasOwnProperty("toString")); // true
// 数组的原型链
var arr = [344,45,34,23];
console.log(arr.__proto__ === Array.prototype); // ture
console.log(arr.__proto__.__proto__ === Object.prototype); // ture
console.log(Array.prototype.hasOwnProperty("push")); // true
console.log(Array.prototype.hasOwnProperty("splice")); // true
</script>
</body>
</html>