~ 解析器在调用函数时,每次都会向函数内部传递进一个隐含的参数 this 。 它指向的是一个对象,这个对象我们成为函数执行的上下文对象。根据函数的调用方式不同,这个 this 指向不同的对象。
function fun () {
console.log (this);
}
fun ();
结果:[object window] 。
function fun () {
console.log (this);
}
var obj = {
name: "孙悟空",
sayName: fun
};
fun ();
结果:[object object] 。
~ 以函数的形式调用时,this 永远是 window 。以方法的形式调用时,this 为对象。
function fun () {
console.log (this.name);
}
var obj = {
name: "孙悟空",
sayName: fun
};
var obj2 = {
name: "沙和尚",
sayName: fun
};
obj.sayName ();
结果:孙悟空。
~ 使用工厂方法来创建对象:所创建的对象类型都是 object 类型,导致我们无法区分出多种不同类型的对象。
~ 构造函数:使用一个构造函数来创建 person 对象。构造函数是一个普通的函数,不同的是构造函数习惯上首字母大写。并且二者的调用方式不同。普通函数是直接调用,而构造函数需要使用 new 关键字来调用。
//创建一个 Person 构造函数:
//(在 Perosn 构造函数中,为每一个对象都添加了一个 sayName 方法。)
//(构造函数每执行一次,都创建一个新的 sayName 方法,即所有实例的 sayName 都是唯一的。)
function Person (name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
//向对象中添加一个方法:
this.sayName = function () {
alert ("hello 大家好,我是"+this.name);
};
}
//创建一个 Person 的实例:
var per = new Person ("孙悟空", 18, "男");
console.log (per);
~ 构造函数的执行流程:1. 构建函数时,立刻创建一个新的对象。2. 将新建的对象设置为函数中的 this ,在构造函数中可以使用 this 来引用新建的对象。3. 逐行执行函数中的代码。4. 将新建的对象作为返回值返回。
~ 使用同一个构造函数创建的对象,我们成为一类对象,也将一个构造函数称为一个类。通过一个构造函数创建的对象,称为是该类的实例。
~ 使用 instanceof 可以检查一个对象是否是一个类的实例。 语法:console.log (per instanceof Person); 如果是则返回 true 否则返回 false 。所有的对象都是 Object 的后代。任何对象和它做检查时都返回 true 。
~ this :1. 当以函数的形式调用时,this 是 window 。2. 当以方法的形式调用时,谁调用方法谁就是 this 。3. 当以构造函数的形式调用时, this 就是新创建的那个对象。
function Person (name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
//向对象中添加一个方法:
this.sayName = fun;
}
//将 sayName 方法在全局作用域中定义
function fun () {
alert ("hello 大家好,我是"+this.name);
};
//创建一个 Person 的实例:
var per = new Person ("孙悟空", 18, "男");
console.log (per);
这样,就不需重复创建多个 sayName 方法。但将函数定义在全局作用域中,污染了全局作用域的命名空间。而且定义在全局作用域中也很不安全。
~ 原型 prototype :我们所创建的每一个函数,解析器都会向函数中添加一个 prototype 属性。这个属性对应着一个对象,这个对象就是我们所谓的原型对象。如果函数作为普通函数调用, prototype 没有任何作用。当函数以构造函数调用时,他所创建的对象中都会有一个隐含的属性,指向该构造函数的原型对象。我们可以通过__proto__来访问该属性
function MyClass () {
}
var mc = new MyClass ();
console.log (mc.__proto__ == MyClass.prototype);
//返回值为 true ,说明二者指向同一个 prototype 对象。
~ 原型对象就相当于一个公共的区域,所有同一个类的实例都可以访问到这个原型对象。我们可以将对象中共有的内容,统一设置到原型对象中。当我们访问对象的一个属性或方法时,它会先在对象自身中寻找,如果有则直接使用,如果没有则会去原型对象中寻找,如果找到则直接使用。
function Person (name, age, gender) {
this.name = name;
this.age = age;
this.gender = gender;
}
//向原型中添加 sayName 方法
Person.prototype.sayName = function () {
alert ("hello 大家好,我是"+this.name);
};
//创建一个 Person 的实例:
var per = new Person ("孙悟空", 18, "男");
var per2 = new Person ("猪八戒", 28, "男");
per.sayName ();
per2.sayName ();
以后我们创建构造函数时,可以将这些对象共有的属性和方法统一添加到构造函数的原型对象中,这样不用分别为每一个对象添加,也不会影响到全局作用域,就可以使每个对象都具有这种属性和方法。
~ 使用 in 检查对象中是否含有某个属性时,如果对象中没有但是原型中有会返回 true 。可以使用对象的 hasOwnProperty () 来检查对象自身中是否有这个属性,如果没有则去原型的原型中寻找,直到找到 Object 对象的原型。若依然没有找到,则返回 null 。 语法:console.log (mc.hasOwnProperty("属性")); 。hasOwnProperty 在原型对象的原型对象中(原型对象也是原象,也有原型。Object 对象的原型没有原型。)。
~ 当我们直接在页面中打印一个对象时,实际上是输出对象的 toString () 方法的返回值。如果我们希望在输出对象时不输出 [Object Object] ,可以为对象添加一个 toString () 方法。
~ 垃圾回收(GC):程序运行过程中会产生垃圾,垃圾积攒过多会导致运行速度过慢。我们需要一个垃圾回收机制来处理程序运行过程中产生的垃圾。当一个对象没有任何的变量或属性对它进行引用(obj = null;),此时我们永远无法操作这个对象,成为垃圾。在 JS 中拥有自动的垃圾回收机制,会自动将这些垃圾对象从内存中销毁。我们不需要也不能进行垃圾回收的操作。只需将不再使用的对象设置为 null 即可。