JavaScript 与 Java 在面向对象编程方面类似,都是引用传递。如
name = ‘小明’
字符串是一个对象,属性字段是指向这个字符串对象的引用。
Java 中的继承,在 JavaScript 中成了原型链,原型链上的每个节点都是一个对象实例,这是与 Java 不同的地方。
对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| var person = { name: '', $age: 0, get getAge() { return this.$age; }, set setAge(age) { if (age < 0) { throw new Error('age can\'t be smaller than 0 : ' + age); } this.$age = age * 10; }, sing: function() { alert(this.name + " is singing"); } } try { person.name = '小明'; person.setAge = 2; alert(person.getAge); person.sing(); } catch (e) { alert(e.message); }
|
在属性前加**$**,则此属性为私有属性,并不会被子类继承。get、set 方法与 function 不同,set 会按照指定逻辑赋值。
继承
1 2 3 4 5 6 7 8 9 10 11
| function Student(id) { this.id = id; } Student.prototype = person; var stu = new Student(1); alert(stu.name); alert(stu.age); stu.name = '小红'; alert(stu.sing()). alert(person.name); alert(JSON.stringify(stu));
|
将 person 设为 Student 的原型,则 Student 继承了 person 的公有方法和公有属性。
修改子类中继承的属性并不会影响到原型的属性,但是如果修改原型的属性,则所有子类的属性都会改变。(跟 Java 内存模型一模一样)
将方法设为prototype可以让浏览器只加载一次方法(为什么?)
1 2 3 4 5 6 7 8 9 10 11 12
| function User(first, last){ this.first = first; this.last = last; } User.prototype.getFullName = function(){ return this.first + " " + this.last; }; User.prototype.getLastName = function(){ return this.last; }; var him = new User("wang", "yang"); console.log(him.getFullName())
|
可能就是因为所有 new User 的对象的原型都指向同一个对象,所以这些 new 出来的对象就不必每个都单独加载 getFullName、getLastName 方法了吧。
这里有更专业的解释Class-based vs. prototype-based languages
原型链
从上面的链接中可以看出 prototype-base 的 JavaScript 一些独特的性质,
- 单继承;一个对象的原型只有一个。
- 运行时对象的属性可以动态增减。
闭包
闭包更像是一个拥有字段和方法的对象实例。
阮一峰
MDN Closure
1 2 3 4 5 6 7 8 9 10
| v = 'global'; var t = { v: 'local', f: function(){ return function(){ return this.v; } } }; console.log(t.f()())
|
f 是 t 的方法,它返回的是一个方法。由于这个返回的方法是在外部被调用,并且 this 关键字会随调用上下文发生变化,所以才会打印 global (this在严格模式下为 undefined,非严格模式下为全局对象)
1 2 3 4 5 6 7 8 9 10 11
| v = 'global'; var t = { v: 'local', f: function(){ var that = this; return function(){ return that.v; } } }; console.log(t.f()())
|
虽然这里也是在外部调用,但是返回值的函数定义上下文的 that 没有被垃圾回收,它指向 t,所以打印的是 local