1、函数和对象
基本概念:
1、函数(function)
2、函数对象(function object)
3、本地对象(native object)
4、内置对象(build-in object)
5、宿主对象(host object)
1.1、函数
//函数声明
function foo(){ }
//函数表达式
var foo = function(){ }
// typeof foo 都是function。
1.2、函数对象
在Javascript中,每一个函数实际上都是一个函数对象。
如果我们单纯的把它当成一个函数使用,那么它就是函数。
如果我们通过他来实例化出对象来使用,那么它就可以当成一个函数对象来使用。
function Foo (){}
var foo = new Foo();
typeof foo // object
1.3、本地对象
typeof(Object) // function
typeof(Array) // function
typeof(Date) // function
typeof(RegExp) // function
// Math和Json 以对象方式存在
typeof(Math) // object
typeof(Json) // object
typeof(null) // object
// 如下:
function Object(){
}
function Array(){
}
可以看出,这些本地对象(类)是通过function建立起来的。
Object原本就是一个函数,通过new Object()之后实例化后,创建对象
1.4、内置对象
定义“由 ECMAScript 实现提供的、独立于宿主环境的所有对象,在 ECMAScript 程序开始执行时出现”。这意味着开发者不必明确实例化内置对象,它已被实例化了。ECMA-262 只定义了两个内置对象,即 Global 和 Math (它们也是本地对象,根据定义,每个内置对象都是本地对象)。
2、原型
2.1 prototype
– 函数的属性
prototype属性是每一个函数
都具有的属性,但是不是一个对象都具有的属性。
Javascript里面所有的数据类型都是对象,为了使JavaScript实现面向对象的思想,就必须要能够实现‘继承’使所有的对象连接起来。而如何实现继承呢?JavaScript采用了类似C++,java的方式,通过new的方式来实现实例。
function Foo(){
}
var foo = new Foo();
foo.__proto__ === Foo.prototype // true
其中Foo中有prototype属性,而foo没有。但是foo中的隐含的proto属性指向Foo.prototype。
2.2 __proto__
函数和对象都有的属性
__proto__
属性是每一个对象以及函数都隐含的一个属性。对于每一个含有__proto__
属性,他所指向的是创建他的构造函数的prototype。原型链就是通过这个属性构件的
function Foo(){
}
var foo = new Foo();
foo.__proto__ === Foo.prototype // true
注意!! Object.prototype.__proto__
指向的是null
// instanceof 一个对象是不是另一个对象 new 出来的
Function instanceof Object //true
Object instanceof Function // true
2.2 constructor
原型对象prototype中都有个预定义的constructor属性,用来引用它的函数对象。这是一种循环引用。
function Foo(){};
console.log(Foo.prototype.constructor === Foo); // true
console.log(Foo.__proto__.constructor === Function); // true
3、关系图
Function.__proto__.__proto__ === Object.prototype //true
Object.__proto__ === Function.prototype //true Object也是Function new出来的
4、题型(参考关系图更好理解)
例1:
function Fn(){
this.x = 100;
this.y = 200;
this.getX = function () {
console.log(this.x);
}
}
Fn.prototype.getX = function () {
console.log(this.x);
};
Fn.prototype.getY = function () {
console.log(this.y);
};
var f1 = new Fn;
var f2 = new Fn;
console.log(f1.getX === f2.getX); //false 自身属性查找,没找到,才找原型上查找
console.log(f1.getY === f2.getY); //true
console.log(f1.__proto__.getY === Fn.prototype.getY); //true
console.log(f1.__proto__.getX === f2.getX); //false
console.log(f1.__proto__.getX === Fn.prototype.getX); //true
console.log(f1.constructor); //Fn f1没有constructor 相当于 (f1.__proto__).constructor === Fn.prototype.constructor
console.log(Fn.prototype.__proto__.constructor); //Object
f1.getX(); //100 this=>f1
f1.__proto__.getX(); //undefined this=>f1.__proto__(Fn.prototype)
f2.getY(); //****** 200 this=>f2
Fn.prototype.getY(); //undefined this=>f2.__proto__(Fn.prototype)
//输出结果: false,true,true,false,true,Fn,Object,100,undefined,200,undefined
例2:
function fun(){
this.a = 0;
this.b = function(){
console.log(this.a);
}
}
fun.prototype = {
b: function(){
this.a = 20;
console.log(this.a);
},
c: function(){
this.a = 30;
console.log(this.a);
}
}
var my_fun = new fun();
my_fun.b(); //0 私有方法 this=>my_fun
console.log(my_fun.a); // 0
my_fun.c(); //30 公有方法 this=>my_fun this.a = 30(将私有属性a修改为30)
console.log(my_fun.a); // 已经修改为30
var my_fun2 = new fun();
console.log(my_fun2.a); // 0 my_fun2重新构造了的
my_fun2.__proto__.c(); // 30 fun.prototype this=>my_fun2.__proto__ 当前实例通过原型链在类的共有属性上增加了一个a:30
console.log(my_fun2.a); // 0 不变
console.log(my_fun2.__proto__.a); //30 c()给原型链赋值 30
例3:
function a(){
}
function b(){
}
var b1 = new b();
a.prototype = b1;
var a1 = new a();
console.log(a1.__proto__.__proto__===b.prototype) //true
console.log(a1.__proto__.__proto__===b.prototype.__proto__) // false
console.log(a1.__proto__.__proto__.__proto__ === Object.prototype) // true
console.log(a1.__proto__.__proto__.__proto__.__proto__ ) // null
console.log(a1.__proto__.constructor === b) //true a1.__proto__等于a.prototype 上面赋值为b1。 相当于b1.constructor === b
console.log(a1.__proto__.__proto__.constructor ===b) // true
console.log(a1.__proto__.constructor === a1.__proto__.__proto__.constructor) // 会如果没找到该属性默认调用__proto__ 去查找
console.log(a1.__proto__.__proto__.__proto__ === Object.prototype) // true 函数原型的__proto__ 最终都指向了 Object.prototype
console.log(a1.__proto__.__proto__.constructor.__proto__ === Function.prototype) // true 构造函数的__proto__ 最终都指向了 Function.prototype