開胃菜javascript
變量的重複聲明是否有影響?
var a = {};
var a;
a;java
一點啓發?設計模式
數組 對象 函數
[] {} function X(){}
new Array() new Object() new X()數組
前面的小問題
(1)函數沒有指定返回值,默認返回什麼? //undefined
(2)js有塊做用域嗎? //只有函數體有做用域
(3)function a(){} a 和 a() 和 new a() 的區別嗎? // a是引用, a()是方法調用, new a()是使用a當構造器來實例出a對象閉包
//傳說中的自修改函數
function a(){
console.log('A');
a = function (){
console.log('B');
};
}
a();
a();app
(4)私有方法和變量?
function a(){
private b;
private c;
function privateD(){}
}
(5)靜態方法和變量?
var a = {};
function b(){};
a.aa='aa';
b.bb='bb'
console.log(a.aa);
console.log(b.bb);
console.log(new b().bb);框架
(6)實例的方法和變量?
function A(){}
var a = new A();
a.b='bbb';
console.log(a.b);
console.log(A.b);函數
(4)(5)(6)總結 Array 舉例???
Array.length --->靜態變量
Array.isArray() --->靜態方法
[1,2,3].push(4) --->實例方法this
(7)一句話解釋閉包? 將function函數內部的做用域開放出來(將一個變量指向外面), 能夠訪問裏面的私有方法和變量.
var getValue,setValue;
(function(){
var num = 0;
getValue = function(){
return num;
}
setValue = function(n){
num = n;
}
})();prototype
(8) function a(){ this.aa='aa'; return {aa:'aaaa'} }; a().aa; //返回值???
function a(){ this.aa='aa'; return {aa:'aaaa'} }; new a().aa; //返回值???
//切記,謹記,務必記住, 當函數返回值是對象的時候, 返回該對象, new仍是直接調用都是返回該對象.
正題:
var a = {}; //這樣寫,隱式調用了Object構造器;
var arr = []; //這樣寫,隱式調用了Array構造器;
var b = {
bb:'bb',
bbb:function(){
return this.bb;
}
};
function c(){
this.cc='cc';
this.ccc=function(){
return this.cc;
}
}
試問上面, b和c功能基本同樣, 寫法的差別各自優缺點??
b優勢:
(1) b簡單直觀,直接建立
b缺點:
(1) b不夠靈活
c優勢
(1) c能夠寫私有方法和變量
(2) c只有new的時候纔會建立實例
(3) c在new實例的時候能夠傳入參數
(4) c能夠return
(5) c能夠在寫法上有等多的自由,好比上面的自修改函數
......優勢太多.......
c缺點
(1) c的缺點是須要new,好麻煩,容易誤用.例以下面的例子:
function a(){
this.b = 'b';
return {c:'c'};
}
var aa = new a();
console.log(aa.b); //undefined
//-----------------------------------構造器----------------------------------------//
構造器屬性(該屬性其實是指向用於建立該對象構造器函數的引用)
function a(){}
a.constructor //function Function() { [native code] }
var aa = new a();
aa.constructor; //function a(){}
var b= {};
b.constructor; //function Object() { [native code] }
JavaScript的都有哪些內建構造器?
Object
Array
Boolean
Number
String
Date
RegExp
Error
Function
由於Object是javascript中全部對象的父對象,因此?
var a = {}; //即便一個空對象, 也有toString(), valueOf()方法;
function a(){};
a.valueOf(); //function a(){}
a.toString(); //"function a(){}"
//-----------------------------------原型----------------------------------------//
每一個"函數"都有一個prototype屬性, 該屬性所存儲的就是原型對象.
(1)在函數定義的時候就建立了,聲明的時候就建立了
(2)prototype的初始值是"空對象"
(3)prototype屬性"構造器函數"的屬性
function a(){} a.prototype;//{};
function a(){} typeof a.prototype; //"object"
自身屬性的優先級高於原型屬性(在原型鏈上查找,先找本身的,再找父親的)
function a(){
this.b='xx';
};
a.prototype = {
b:'bb',
c:'cc'
};
var aa =new a();
aa; //{b: "xx", c: "cc"}
__proto__???
var parent = {
b:'bb',
c:'cc'
}
function child(){};
child.prototype = parent;
var ren = new child();
console.log(ren);
提問? 怎麼從ren這個實例對象上獲取原型對象???
console.log(ren.prototype); //undefined; 爲何undefiend???
(1)找到構造器
ren.constructor
(2)再找到構造器的原型
ren.constructor.prototype
console.log(ren.constructor.prototype === parent ); //true ?? 媽的,我沒測出來
也能夠這樣
console.log(ren.__proto__ === parent); //true
提問: __proto__ 和 prototype 同樣嗎??? 徹底不同啦
__proto__ 是對象實例查找原型的屬性, prototype是構造器函數的屬性,
//-----------------------------------繼承(最複雜,最博大精深)-----------------------------------//
原型坑
(1) 當咱們對原型徹底替換,可能會觸發原型鏈的某種異常
(2) prototype.constructor 屬性是不可靠的
function Dog(){
this.tail = true;
}
var tom = new Dog();
Dog.prototype.say = function(){
return 'Woof';
}
console.log( tom.say() ); //Woof
console.log( tom.constructor ); //Dog()
console.log( tom.constructor.prototype.constructor ); //Dog();
console.log( typeof tom.constructor.prototype.tail ); //undefined;
Dog.prototype = {paws:4,hair:true};
console.log( tom.say() ); //出問題了!!!! 由於__proto__
繼承的寫法
(1) 只繼承原型, 說缺點??
function a(){};
a.prototype.name='shape';
function b(){};
b.prototype = a.prototype;
b.prototype.constructor=b;
function c(){};
c.prototype = b.prototype;
c.prototype.constructor=c;
(2) 臨時構造器, new F() 第一種相對不錯的繼承寫法
function a(){};
a.prototype.name='shape';
function f(){};
f.prototype = a.prototype;
var ff = new f();
console.log(ff.name); //shape
//人類發明了這個方法, 成熟的js框架隨處可見這個方法
function extend(child,parent){
var f = function(){}
f.prototype = parent.prototype;
child.prototype = new f();
child.prototype.constructor=child;
child.uber = parent.prototype; //添加一個指向父級原型的引用
}
(3) 屬性copy 第二種繼承寫法
function extend2(child,parent){
var p = parent.prototype;
var c = child.prototype;
for(var i in p){
c[i] = p[i];
}
c.uber = p;
}
//說缺點?? 提示: 對象類型(函數和數組),都是引用傳遞, 函數自己不會被再次建立.
var a = function(){};
var b = function(){};
a.prototype.arr = [1,2,3];
extend2(b,a);
b.prototype.arr.push(4,5,6);
console.log(a.prototype.arr); //[1, 2, 3, 4, 5, 6]
//擴展: 淺copy和深copy的繼承寫法, 成熟的js框架隨處可見這個方法
(4) 對象間繼承 object() 第三種繼承寫法
//優秀的常規寫法
function extendCopy(p){
var c = {};
for(var i in p){
c[i] = p[i];
}
c.uber = p;
return c;
}
//做者 Douglas Crockford
function object(o){
function f(){};
f.prototype = o;
n = new f();
n.uber = o;
return n;
}
//出處: javascript權威指南 122頁 優秀示例
function inherit(p){
if( p === null ) throw TypeError();
if( Object.create ){
return Object.create(p);
}
var t = typeof p;
if( t !== 'object' && t !== 'function' ){ throw TypeError(); }
function f(){};
f.prototype = p;
return new f();
}
//這樣寫繼承好處多多
var a = Object.create({});
(5)多重繼承
function multi(){
var n = {};
for(var j=0; j<arguments.length; j++){
var stuff = arguments[j];
for(var i in stuff){
n[i] = stuff[i];
}
}
return n;
}
var a = {aa:'aa',aaa:'aaa'};
var b = {bb:'bb',bbb:'bbb'};
var c = multi(a,b);
console.log(c); //{aa: "aa", aaa: "aaa", bb: "bb", bbb: "bbb"}
(6)混合繼承
function triangle(o,s,h){
function f(){};
f.prototype = o;
n = new f();
n.uber = o;
n.s = s;
n.h = h;
return n;
}
(7)構造器借用繼承
//初級玩法
function a(){
this.aa='aa';
};
function b(){
a.apply(this,arguments);
};
var bb = new b();
console.log(bb.aa); //aa
//高級玩法
function a(){
this.aa='aa';
};
function b(){
this.extend = function(){
var arg = [].slice.call(arguments,1);
(arguments[0]).apply(this,arg);
};
};
var bb = new b();
bb.extend(a);
console.log(bb.aa); //aa
結束語:
繼承寫法是能夠組合的, 夠變態吧!!! js繼承有至少幾十種寫法
function child(){
parent.apply(this,arguments);
}
extend2(child,parent);
命名空間
初始化分支
延遲執行
鏈式調用
設計模式
單例
工廠
門板
裝飾器
觀察者
發佈訂閱
如今再來體會下面這句話: