CoffeeScript 中對象的綁定
有時(shí)候你需要一個(gè)函數(shù)運(yùn)行在特定的上下文對象中,而不管它在哪里被調(diào)用。比如有類似這樣一個(gè)函數(shù):
callback = (message) –> @v.push message
當(dāng)直接調(diào)用這個(gè)函數(shù)時(shí) @(this)所代表的就是全局對象,如果通過 call 或者 apply 指定了其他的上下文對象,@ 則代表了其他上下文對象。有什么辦法使 @ 綁定為特定的上下文對象呢?
在 CoffeeScript 中有一個(gè)非常方便的方式,只要用 => 代替 –> 定義需要綁定特定上下文對象的函數(shù)即可,比如以上 callback 函數(shù):
callback = (message) => @v.push message
此時(shí)的 @ 指代的就是該函數(shù)定義時(shí)所在的上下文對象。以上函數(shù)解析成 javascript 就是:
var callback,
_this = this;
callback = function(message) {
_this.v.push(message);
};
那為什么不直接用 => 代替 –> 呢?
增加了代碼量以及運(yùn)行時(shí)間,并且這是沒有必要的
為了適應(yīng)復(fù)雜的上下文對象,可以提供更加優(yōu)雅的代碼編寫方式
在你定義函數(shù)的時(shí)候一定要非常認(rèn)真考慮使用 this/@ 指定正確的上下文對象。同時(shí)使用綁定和 call/apply 方法編寫更優(yōu)雅的代碼。
CoffeeScript面向?qū)ο缶幊?/strong>
CoffeeScript的面向編程的語法同JavaScript比較起來,真是天上地下。一個(gè)陽春白雪,一個(gè)下里巴人。但是有一點(diǎn)我們要記?。篊offeeScript只是編譯到JavaScript,它只是在JavaScript的基礎(chǔ)上進(jìn)行了語法的抽象,本質(zhì)上還是JavaScript。
類
CoffeeScript采用class關(guān)鍵字聲明類,整個(gè)語法看起來更加簡明流暢。
#編譯前
class Animal
constructor: (name)->
@name = name
printName: ->
console.log(@name)
animal = new Animal 'animal'
animal.printName() #animal
#編譯后
var Animal, animal;
Animal = (function () {
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function () {
return console.log(this.name);
};
return Animal;
})();
animal = new Animal('animal');
animal.printName();
constructor是構(gòu)造函數(shù),就上面的例子來說,還可以簡寫,實(shí)際上效果是一樣的
class Animal
constructor: (@name)->
printName: ->
console.log(@name)
animal = new Animal 'animal'
animal.printName() #animal
CoffeeScript將我們習(xí)慣性的書寫方式變成豐富的語法糖。說到這里我就想說一句了,能不能把構(gòu)造函數(shù)換個(gè)字符,constructor丫太長了。
繼承
繼承使用的是extends關(guān)鍵字
#編譯前
class Animal
constructor: (@name)->
printName: ->
console.log(@name)
class Cat extends Animal
cat = new Cat 'cat'
cat.printName() #cat
#編譯后
var Animal, Cat, cat,
extend = function (child, parent) {
for (var key in parent) {
if (hasProp.call(parent, key)) child[key] = parent[key];
}
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
child.__super__ = parent.prototype;
return child;
},
hasProp = {}.hasOwnProperty;
Animal = (function () {
function Animal(name) {
this.name = name;
}
Animal.prototype.printName = function () {
return console.log(this.name);
};
return Animal;
})();
Cat = (function (superClass) {
extend(Cat, superClass);
function Cat() {
return Cat.__super__.constructor.apply(this, arguments);
}
return Cat;
})(Animal);
cat = new Cat('cat');
cat.printName();
extend函數(shù)解析
我們簡單分析下編譯后的extend函數(shù),對JavaScript原型鏈不是很熟的可以跳過這段。兩個(gè)參數(shù)分別是子類child和父類parent,第一段代碼:
for (var key in parent) {
if (hasProp.call(parent, key)) child[key] = parent[key];
}
這段代碼就是將父類上面的屬性拷貝到子類上,因?yàn)镴avaScript當(dāng)中函數(shù)也是對象,可以擴(kuò)展屬性的。什么意思?看代碼
class Animal
constructor: (@name)->
printName: ->
console.log(@name)
Animal.prop = 'Animal prop'
class Cat extends Animal
console.log Cat.prop #Animal prop
第二段代碼:
function ctor() {
this.constructor = child;
}
ctor.prototype = parent.prototype;
child.prototype = new ctor();
可能大家看不大明白,我稍微改動下,換種寫法
child.prototype = new parent();
child.prototype.constructor=child;
這里就是我們上面提到的原型鏈繼承。再看最后段代碼:
child.__super__ = parent.prototype;
這里是為了在子類中調(diào)用父類的方法,實(shí)現(xiàn)多態(tài),看下面的例子就知道了。
多態(tài)
編譯后的代碼太長,就不粘貼了,看CoffeeScript代碼更易于學(xué)習(xí)。
直接重寫父類方法
class Animal
constructor: (@name)->
printName: ->
console.log(@name)
class Cat extends Animal
printName: ->
console.log 'Cat name:' + @name
cat = new Cat 'cat'
cat.printName() #Cat name:cat
重寫父類方法,在重寫的方法中調(diào)用父類方法
class Animal
constructor: (@name)->
move: (meter)->
console.log(meter)
class Cat extends Animal
move: ->
console.log 'Cat move'
super 4
cat = new Cat 'cat'
cat.move() #Cat move 4
更多建議: