this
默认绑定规则
函数的独立调用。test()
this就是指向window。
隐式绑定规则
通过对象的方法调用,谁调用就指向谁。
如上图,31行的this,是由obj.foo()调用的,即对象的方法,故该this指向obj
34行的this,由text()独立调用,指向window。
立即执行函数也是window。
这两个函数的this是否相等,是由函数的执行方式决定的。
闭包,当函数执行的时候,导致函数被定义,并抛出;
上图情况,this指向window。
隐式丢失。如下图:
这是将函数赋值给bar,bar就和obj没有任何关系了,再调用bar也就是独立调用。
参数赋值:
上图也是指向window。
父函数是由能力决定子函数this指向的。
显示绑定:
call
,apply
,bind
强绑定this指向。
new绑定:
即当函数以构造函数的形式出现时,this指向新建的对象。
一般不会指定return。
使用工厂方法创建对象
使用工厂模式创建的对象,使用的构造函数都是Object,所以创建的对象都是Object这个类型,导致我们无法区分出多种不同类型的对象。
创建一个构造函数
构造函数和普通函数的区别就是调用方式的不同,普通函数就是直接调用,而构造函数需要使用new关键字来调用。
首字母大写。
调用构造函数时,立刻创建一个新的对象。将新建的对象设置为函数中的this,在构造函数中可以引用this来指向新建的对象。。逐行执行函数中的代码。将新建的对象作为返回值返回。
function Person(name, gender){
this.name = name;
this.gender = gender;
}
ver per = new Person();
使用同一个构造函数创建的对象,我们称为一类对象,也将一个构造函数称为一个类。
使用instanceof
可以检查一个对象是否是一个类的实例。
console.log(per instanceof Person)
所有的对象和Object做instance检查时都会返回true。
优化:
每次创建一个新的对象,都会创建一个sayName(方法)。
创建1000个对象,就会创建1000个一模一样的方法,这是完全没有必要的。
解决方法:
将sayName方法提取出来,定义在全局作用域中。
但也存在问题,将函数定义在全局作用域中,污染了全局作用域的命名空间,而且定义在全局作用域中很不安全。
原型对象
原型prototype。我们所创建的每一个函数,解析器都会向函数中添加一个属性prototype。
如果函数作为普通函数调用,prototype没有任何作用。
当函数以构造函数调用时,所创建的对象中都会有一个隐含的属性,指向该对象的原型对象,可以通过 __proto__
来访问该属性。
原型对象就相当于一个公共区域,所有同一个类的实例都可以访问到这个原型对象,我们可以将对象中共有的内容,统一设置在原型对象中。
当我们访问对象的一个属性或方法中,先在对象自身中寻找,如果有则直接使用,如果没有就回去原型对象中找。
使用in检查对象中是否有某个属性时,如果对象中没有,原型中有,也会返回true。
console.log("name" in mc);
可以使用hasOwnProperty()方法:
console.log(mc.hasOwnProperty("hasOwnProperty")) //false
console.log(mac.__proto__.hasOwnProperty("hasOwnProperty"))
如果原型对象中没有,则去原型的原型中寻找,如上图,hasOwnProperty就在原型的原型中。直到找到Object的原型,Object没有原型。