一、原型
1. prototype
原型prototype是函数的一个属性,打印出来出来其实也是对象
这个prototype是定义构造函数构造出来的每个对象的公共祖先
通过该构造函数构造出来的实例对象都可以继承原型上的属性和方法。
function Handphone(color, brand, system) {
this.color = color;
this.brand = brand;
this.system = system;
}
Handphone.prototype = {
rom: '64G',
ram: '6G',
screen: '18:9',
system: 'Android',
call: function () {
console.log('I am calling somebody');
}
}
var hp1 = new Handphone('black', 'iPhone', 'IOS');
console.log(hp1);
注意:自己有的属性就不会去原型上找
2. constructor
原型prototype的一个属性,指向该构造函数
所有该构造函数构造出的对象都可以继承原型上的属性和方法。可以被更改。
function Handphone(color, brand, system) {
this.color = color;
this.brand = brand;
this.system = system;
}
function Telephone() {}
// 可以更改对象的构造函数
Handphone.prototype = {
constructor: Telephone
}
二、原型链
1. proto
构造函数通过new实例化对象,生成_proto_属性,该属性是一个对象,指向该构造函数的原型。实例化对象通过_proto_属性可以访问到该构造函数原型上的属性和方法,形成原型链。
function Car() {
// var this = {
// __proto__: Car.prototype
// }
}
Car.prototype.name = 'Benz';
var car = new Car();
console.log(car);
注意:原型是属于实例化对象的不是属于构造函数的,proto只是装原型的容器
当this下面有name属性时就取用,但是没有的话就会在本身的this当中的_proto_属性中调用。也就是说是在实例化对象上面的,并不是在Car()上面的
2. _proto_是可以更改的
function Person(){}
Person.prototype.name='张三';
var p1={
name:'李四'
}
var person=new Person();
console.log(person.name);//张三
person._proto_=p1;
console.log(person.name);//李四
3. 案例分析
function Car() { }
Car.prototype.name = 'Mazda';
var car = new Car();
Car.prototype.name= 'Benz';
console.log(car.name); // 'Benz'
// 构造函数的原型添加name属性
Car.prototype.name = 'Benz';
function Car() { }
var car = new Car();
// 构造函数的原型指向新的对象
Car.prototype = {
name: 'Mazda'
}
// 实例化出来的对象的__proto__属性指向的是未修改前的Car.ptototype对象
console.log(car.name); // 'Benz'
console.log(car);
//--------------------------------
function Car() { }
Car.prototype.name = 'Mazda';
var car = new Car();
Car.prototype.name= 'Benz';
console.log(car.name); // 'Benz'
// 构造函数的原型添加name属性
Car.prototype.name = 'Benz';
function Car() { }
var car = new Car();
// 构造函数的原型指向新的对象
Car.prototype.name = 'mazda'
console.log(car.name); // 'mazda'
console.log(car);
注意:实例化出来的对象proto才会保存prototype对象,实例化后定义的prototype对象不在proto上,所以上面打印benz而不是马自达。下面这个只是給某个属性修改值,实例化的对象里的proto指向的是prototype,改变里面的属性就相当于覆盖了之前的值,所以可以打印出来。
三、闭包立即执行函数
1. return形成闭包,将函数内部的AO返回到全局。
function test() {
var a = 1;
function plus1() {
a++;
console.log(a);
}
return plus1;
}
var plus = test();
plus();
plus();
plus();
2. window,将属性和方法挂到全局对象window上,实现全局访问。
function abc() {
window.a = 3;
}
abc();
console.log(a); // 3
function test() {
var a = 1;
function add() {
a++;
console.log(a);
}
window.add = add;
}
test(); // 执行后,可以在全局环境下访问到add方法
add();
add();
add();
3. lIFE,声明一个全局变量接收函数返回值,或者直接挂载到window对象上。
var add = (function () {
var a = 1;
function add() {
a++;
console.log(a);
}
return add;
})();
//-----------------------------------------------------------------------------------------
;(function () {
var a = 1;
function add() {
a++;
console.log(a);
}
window.add = add;
})();
add();
add();
add();
4. 构造函数构成闭包
function Text(){
var a = 1;
this.add = function(){
a++;
console.log(a);
}
//隐式返回this return this
}
var text = new Text();
四、插件开发
有效隔离全局作用域,避免变量污染
(function(){
function Test(){}
window.Test=Test;
})();
var test =new Test();)
五、作业
写一个插件,任意传两个数字,调用插件内部方法可进行加减乘除功能
;(function () {
function Compute(opt) {
this.x = opt.firstNum || 0;
this.y = opt.secondNum || 0;
}
Compute.prototype = {
plus: function () {
return this.x + this.y;
},
minus: function () {
return this.x - this.y;
},
mul: function () {
return this.x * this.y;
},
div: function () {
return this.x / this.y;
}
}
window.Compute = Compute;
})();
var compute = new Compute({
firstNum: 1,
secondNum: 2
});
console.log(compute.plus());
console.log(compute.minus());
console.log(compute.mul());
console.log(compute.div());