10.1原型
什么是原型
- 原型
prototype
其实是 function 对象的一个属性,结果它也是对象
function Handphone(){
}
console.log(Handphone.prototype);//{constuctor: f}
- 这个 prototype 是定义构造函数构造出的每个对象的公共祖先,所有被该构造函数构造出的对象都可以继承原型上的属性和方法
- 自己有的属性,就不会再去原型上去找
function Handphone(color, brand){
this.color = color;
this.brand = brand;
this.screen = '18:9';
this.system = 'Android';
}
Handphone.prototype.rom = '64G';
Handphone.prototype.ram = '6G';
Handphone.prototype.screen = '16:9';
var hp1 = new Handphone('red', '小米');
var hp2 = new Handphone('black', '华为');
console.log(hp1.rom);//64G
console.log(hp2.ram);//6G
console.log(hp1.screen); // 18:9
为什么所有的方法都写到原型上,为什么只有部分属性会写到函数内部?
- 在实例化的时候,总有些写死的值,每次 new 的时候,都要走一遍流程,属于代码的冗余。
- 因为属性往往都是配置项,而方法都是一样的,所以通用的属性和方法会写到原型上,需要动态改变的属性才放在构造函数上写
通过构造出来的实例对原型的增删改查
通过实例化对象增删改祖先prototype上的东西是不可行的
function Test() {
}
Test.prototype.name = 'prototype';
var test = new Test();
// 查
console.log(test.name);
// 添加
test.num = 1;
// 构造出来的对象添加东西不可行,不会增加到prototype上
console.log(Test.prototype, test);
// 删除,也影响不了prototype,删除的是实例化出来的对象自身的
delete test.name;
console.log(Test.prototype, test);
// 修改, 不可行
test.name = 'proto';
console.log(Test.prototype, test);
以对象的方式给原型赋值
function Handphone(color, brand, system){
this.color = color;
this.brand = brand;
this.system = system;
}
Handphone.prototype = {
rom: '64G',
ram: '6G',
screen: '18:9',
call: function(){
console.log('I am calling somebody');
}
};
var hp1 = new Handphone('red', 'iphone', 'IOS');
console.log(hp1);
console.log(hp1.constructor);
consturctor 指向的是构造函数本身
function Handphone(color, brand, system){
this.color = color;
this.brand = brand;
this.system = system;
}
console.log(Handphone.prototype);
通过构造函数.prototype里面的constructor可改变构造器指向
function Telphone() {}
function Handphone(color, brand, system){
this.color = color;
this.brand = brand;
this.system = system;
}
Handphone.prototype = {
constructor: Telphone
}
console.log(Handphone.prototype);
function Car() {
// 隐式的 var this = {}; // 这个this指的就是实例化对象 car
// proto 是实例化以后,属于的是对象实例,如果没有实例化,不存在proto,不属于构造函数
// __proto__ 就是装 prototype 的容器,就是为了给 prototype 定义一个键名
}
Car.prototype.name = 'Benz';
var car = new Car();
console.log(car); // proto是实例化以后的结果
为什么能访问到car.name
this自身没有,找到__proto__,然后访问__proto__对应的prototype
proto属于每一个实例化的对象,而不是属于某个构造函数总结:
当构造函数被new实例化的时候,产生了 this, this中默认给了__proto__装了实例化之后的原型,prototype没被额外赋值时,默认有constructor,constructor构造器默认指向构造函数本身,构造器构造出来的是Car的实例
__proto__是一个属性,属性值可以修改
function Person() {
}
Person.prototype.name = '张三';
var p1 = {
name: '李四'
}
var person = new Person();
console.log(person.name); // 张三
person.__proto__ = p1;
console.log(person.name); // 李四
//person.__proto__ === Person.prototype
给prototype属性赋值
function Car(){}
Car.prototype.name = 'Mazda';
var car = new Car();
// 给属性赋值
Car.prototype.name = 'Benz';
console.log(car.name); // Benz
重写prototype
Car.prototype.name = 'Benz';
function Car(){}
var car = new Car();
// 重写 prototype
Car.prototype = {
name: 'Mazda'
}; // 重写 prototype 是在实例化之后写的,没有实例化,修改的是实例化之前的prototype, 实例化之前的prototype保存在constructor所对应的构造函数的prototype中
console.log(car.name); // Benz
重写 prototype 是在实例化之后写的,没有实例化,修改无效 constructor
中保存的是实例化之前的东西,实例化之后就变成了对象
10.2插件开发
window return
function test() {
var a = 1;
function plus1(){
a++;
console.log(a);
}
return plus1;
}
var plus = test(); // 相当于 plus1 变成了全局函数
plus();
plus();
plus();
// 2 3 4
function test() {
var a = 1;
function add(){
a++;
console.log(a);
}
window.add = add; // 也形成了闭包
}
test();
add();
add();
add();
// 2 3 4
var add = (function(){
var a = 1;
function add(){
a++;
console.log(a);
}
return add;
})();
add();
add();
add();
// 2 3 4
(function(){
var a = 1;
function add(){
a++;
console.log(a);
}
window.add = add;
})();
add();
add();
add();
// 2 3 4
两个方法功能相同
js插件
(function(){ // 防止变量污染、函数作用域污染、隔离全局作用域
function Test(){
}
Test.prototype = {}
window.Test = Test;
})();
var test = new Test();
写立即执行函数默认先打一个分号,要不然两个立即函数一起会报错
;(function(){})()
;(function(){})()
应用
;(function(){
var Compute = function(opt){
}
Compute.prototype = {
plus: function(n1, n2){
console.log(n1 + n2);
},
minus: function(n1, n2){
console.log(n1 - n2);
},
mul: function(n1, n2){
console.log(n1 * n2);
},
div: function(n1, n2){
console.log(n1 / n2);
}
}
window.Compute = Compute;
})();
var compute = new Compute();
compute.plus(2, 3);
compute.minus(7, 3);
compute.mul(4, 3);
compute.div(9, 3);