061 this
解析器在调用函数每次都会传递一个隐含参数 this,指向的对象称为函数的上下文对象;根据函数调用方式不同,this 指向不同对象
- 函数调用:指向 Window
- 方法调用:指向对象
- 构造函数调用:指向创建的对象
062 this 补充
以下的程序总是输出全局变量,需要修改为 this.name
var name = "全局变量";
function fun() {
console.log(name); // 必须改成this.name才能输出局部变量
}
var obj = {
name: "局部变量",
sayName: fun
};
063 使用工厂方法创建对象
更“优雅”地生产对象;大量重复代码的提取
function createPerson(name, age, gender) {
var obj = new Object();
obj.name = name;
obj.age = age;
obj.gender = gender;
obj.sayName = function() {
alert(this.name);
}
return obj;
}
let obj1 = createPerson("qwerty", 100, "female");
064 构造函数
new Object();
就是构造函数
构造函数习惯上首字母大写
构造函数需要用 new 关键字调用,与普通函数只是调用方式不同
构造函数执行流程
- 立刻创建新对象
- 将新建对象设置为函数中的 this,构造函数中可以使用 this 来引用
- 逐行执行函数代码
- 将新建的对象作为返回值返回
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = function() {
alert(this.name);
}
}
let per = new Person("123", 15, "male");
同一构造函数创建的对象称为一类对象,构造函数称为一个类
构造函数创建的一个对象称为该类的实例
instanceof 关键字:检查是否是类的实例(用法:对象 instanceof 类
)
所有对象都是 Object 的后代,任何对象用 instanceof Object 都是 true
065 构造函数修改
在构造函数中,为每一个对象都添加了 sayName 方法,每执行一次会创建一个新的 sayName 方法
完全可以使所有对象共享一个方法,就是在全局定义
function Person(name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
this.sayName = fun;
}
function fun() {
alert(this.name);
}
066-067 原型对象
函数定义在全局作用域会污染全局作用域命名空间,而且不安全
原型 prototype:创建的每一个函数,解析器都会向函数中添加一个属性 prototype,这个属性对应的对象就是原型对象
当函数以构造函数形式调用时,它所创建的每一个对象都有一个隐含属性,指向该构造函数的原型对象,可以通过 __proto__
访问
原型对象相当于公共区域,所有同一个类的实例都可以访问原型对象,可以将对象共有内容统一设置到原型对象中
当访问对象的属性或方法时,会先在对象自身中寻找,没有的话会去原型对象中找
prototype
用于类,__proto__
用于实例;二者指向的东西是相同的
function MyClass() {
}
MyClass.prototype.name = "原型的名字";
MyClass.prototype.sayHello = function() {
alert("Hello!");
}
用 in 检查对象中某个属性,如果原型中有,也会是 true
可以用 hasOwnProperty() 来检查对象自身的属性
原型对象也是对象,它也有原型
Object 对象的原型没有原型,如果在 Object 中依然没有找到,会出现 null
let a = new MyClass();
console.log(a.hasOwnProperty("name")); // false
console.log(a.hasOwnProperty("hasOwnProperty")); // false
console.log(a.__proto__.hasOwnProperty("hasOwnProperty")); // false
console.log(a.__proto__.__proto__.hasOwnProperty("hasOwnProperty")); // true
console.log(a.__proto__.__proto__.__proto__); // null
068 toString()
直接在页面中打印对象,输出的是对象的 toString() 方法的返回值
如果希望不输出 [object Object]
,可以为对象添加 toString() 方法
Person.prototype.toString = function() {
return "name" + this.name;
}
069 垃圾回收 GC
当一个对象没有任何变量或属性引用,这个对象就是垃圾,会导致程序运行变慢,所以必须回收
JS 有自动垃圾回收机制,自动将垃圾对象从内存中销毁,程序员不需要也不能进行垃圾回收
只需要将不再使用的对象设置为 null
var obj = new Object();
obj = null;
070 数组简介
前面讨论的对象都是自定义对象,自定义对象不是主要用的对象
内建对象:数组 Array
- 数组也是对象
- 与普通对象功能类似,用来存储值
- 不同的是普通对象使用字符串作为属性名,而数组使用数字作为索引
- 索引:从 0 开始的整数
- 数组的存储性能比普通对象更好,在开发中常用
创建数组
对数组用 typeof 返回 "object"
let arr = new Array();
添加元素
语法:数组[索引] = 值
arr[0] = 10;
arr[1] = 33;
arr[2] = 22;
读取元素
console.log(arr[1]); // 33
console.log(arr[3]); // undefined
数组长度 length
连续数组:等于元素个数
非连续数组:等于最大索引+1;尽量不要创建非连续数组
console.log(arr.length);
修改 length:如果修改的 length 大于原长度,则多出的部分会空出来;如果 length 小于原长度,则多出的元素会删除
向数组末尾添加元素
arr[arr.length] = 70;