一、知识点:
-constructor
-this
-原型继承
-原型链
-应用
二、constructor
这里的构造器是指对象的构造器,也可以叫对象类型。
//new operator
var o = new <span style="color:#ff0000;">Object();</span>
var a = new <span style="color:#ff0000;">Array();</span>
var d = new <span style="color:#ff0000;">Date(); //对象构造器,constructor</span>
//object literal
var o = {x:1};
var a = {1,2,3};
1、自定义constructor
使用函数来创建自定义的构造器
function Employee(name,company,salary){
<span style="color:#ff0000;">this</span>.name = name;
<span style="color:#ff0000;">this</span>.company = company;
<span style="color:#ff0000;">this</span>.salary = salary;
<span style="color:#ff0000;">this</span>.changeSalary = function(salary){ //使用this来创建对象属性,js中没有明确区分属性和方法,函数类型的属性就是我们常说的方法
this.salary = salary;
}
}
2、 三种形式
function Employee(){} //函数的定义
var Employee = function(){} //函数表达式
var Employee = new Function();
3、注意:
所有的函数都可以当成constructor?
错误。
var o = <del><span style="color:#ff0000;">new</span></del> Math.min();//不可以作为构造器,不能使用new
当一个function有return时:
在使用new关键字来创建构造器的对象时,如果构造器的返回值是一个对象类型的话,就直接将这个对象作为新创建出来的对象;其他的情况就是创建一个新的对象。
//constructor
function Employee(name,company,salary){
this.name = name;
this.company = company;
this.salary = salary;
this.changeSalary = function(salary){
this.salary = salary;
}
return<span style="color:#ff0000;"> {}</span>;
}
var jim = new Employee('Jim Green', 'NetEase', 30000);
alert(jim.name);
这里创建的jim对象就是一个空对象,alert出来的就是undefined,因为从这个对象里面是找不到这个属性的。
三、this
1、在不同环境下的this值:
1.1 全局下的this值
var a = 10;
alert(this.a);
this.b = 20;
alert(b);
c = 30;
alert(this.c);
this指的是全局对象,在浏览器中就是window对象,在其他环境中可能就不是window对象,比如在nodejs中就不是window对象。
1.2 构造器下的this
指的是我们将要创建出来的新的对象。
1.3 函数中间的this
函数中的this指向函数的调用者。
1.4 new Function中的this
指的都是全局对象window
(function(){
var f = new Function('alert(<span style="color:#ff0000;">this</span>)');
f();
})();
function Foo(){
this.bar = function(){
var f = new Function('alert(<span style="color:#ff0000;">this</span>)');
f();
}
}
var foo = new Foo();
foo.bar();
1.5 eval中的this
(function(){
eval('alert(<span style="color:#ff0000;">this</span>)'); //window对象,因为在闭包中,是指的全局global对象
})();
function Foo(){
this.bar = function(){
eval('alert(<span style="color:#ff0000;">this</span>)'); //跟bar中的this一样
}
}
var foo = new Foo();
foo.bar();
eval中的this指的是调用上下文中的this。
1.6 apply、call
可以改变this的指向:
//apply and call
function Point(x,y){
this.x = x;
this.y = y;
this.move = function(x,y){
this.x += x;
this.y += y;
}
}
var point = new Point(0,0);
point.move(1,1);
var circle = {x:0, y:1, r:1};
point.move.apply(circle,[1,1]);
point.move.call(circle, 1, 1);
四、原型
1、概念:原型(prototype)是构造器(constructor)的一个属性。
//Teacher constructor
function Teacher(){
this.courses = [];
this.job = 'teacher';
this.setName = function(name){
this.name = name;
}
this.addCourse = function(course){
this.courses.push(courses);
}
}
var bill = new Teacher();
bill.setName('Bill');
bill.addCourse('math');
var tom = new Teacher();
tom.setName('Tom');
tom.addCourse('physics');
bill对象与tom对象有相同的属性和方法,这样写太浪费内存。
应用原型改进:
//Teacher constructor
function Teacher(){
this.courses = [];
}
Teacher.prototype = {
job:'teacher',
setName:function(name){
this.name = name;
},
addCourse:function(course){
this.courses.push(courses);
}
}
2、原型链
2.1 原型链的作用:
js中对象属性的查找、修改和删除都是通过原型链来完成的。
-属性查找
在上面的图中,我们看tom对象,属性的查找是顺着原型链来查找的,当在自身上找不到属性时,就到原型上去找。
-属性修改
属性修改永远修改的是对象自身的属性,不管属性名字是来自对象本身,还是它的原型。如果对象本身没有这个属性,就增加这个属性到这个对象本身:
tom.job = 'assistant';
此时,会在tom对象上添加一个属性job,并将它赋值为“assistant”。这样是无法修改到对象原型上的属性值的。
想要修改的话,在这个例子中可以用到 “Teacher.prototype.属性名 = ....” 来修改。
修改了原型对象上的属性是会影响到所有通过该构造器中的原型创建出来的对象的。
-属性删除
属性删除也只能删除对象自身的属性。
2.2 思考:
如何判断一个属性来自于对象本身?
在js中有一个方法可以用来判断:
//hasOwnProperty
tom.hasOwnProperty('job'); //false
3、ES5中的原型继承
-Object.create(proto[,propertiesObject])
可以直接在原型对象的基础上创建一个新对象。原来是通过构造器来完成的,就是要new。
//Object.create
var teacher = {
job:'teacher',
courses:[],
setName:function(name){
this.name = name;
},
addCourse:function(course){
this.courses.push(course);
}
}
var bill = Object.create(teacher);
bill.setName('Bill');
<em><span style="color:#ff0000;">bill.addCourse('math');</span></em>
思考:
如何在低版本浏览器实现Object.create功能?
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create
五、JS面向对象编程
1、知识点
-全局变量
-封装
-继承
2、全局变量
2.1 三种定义方式
①在最外层用 var 定义:使用delete是无法成功删除的。
var test = 'some value';
②
window.test = 'some value';
③
(function(){
var a;
test = 'some value';
})();
后两种都是定义在了window对象上,使用delete可以删除。
2.2 信息隐藏
3、封装
4、继承
4.1 类继承
(function(){
function ClassA(){}
ClassA.classMethod = function(){}
ClassA.prototype.api = function(){}
function ClassB(){
ClassA.apply(this, arguments);
}
ClassB.prototype = new ClassA();
ClassB.prototype.constructor = ClassB;
ClassB.prototype.api = function(){
ClassA.prototype.api.apply(this, arguments);
}
var b = new ClassB();
b.api();
})();
4.2 原型继承
(function(){
var proto = {
action1: function(){
//TODO
},
action2: function(){
//TODO
}
}
var obj = Object.create(proto); //以proto为原型
})();
在低版本中实现Object.create方法:
var clone = (function(){
var F = function(){};
return function(proto){
F.prototype = proto;
return new F();
}
})();
这是利用prototype的特性写的。没有完全实现Object.create方法的效果,不能定义属性。