(原型和原型链基础)
目录
原型基础
更改原型
原型和原型链
包装类和隐式转换
课后作业
一、原型基础
- 用构造函数来讲,原型就是function对象的一个属性,打印出来会看到其实原型也是一个对象
prototype是定义构造函数构造出的每个对象的公共祖先
- 所有被该构造函数构造出的对象都可以继承原型上的属性和方法
- 自己有的属性不会从原型上找
- 一般需要配置的属性会写到构造函数内(传参),方法和写死的属性会放到原型里
// 原型prototype其实是function对象的一个属性
//这个prototype是定义构造函数构造出的每个对象的公共祖先
function HandPhone(color, brand) {
this.color = color
this.brand = brand
this.screen = "18:9"
this.system = "Android"
}
// console.log(HandPhone.prototype)
// 打印出来结果它也是对象
HandPhone.prototype.rom = "64G"
HandPhone.prototype.ram = "6G"
let hp1 = new HandPhone("red", "小米")
let hp2 = new HandPhone("black", "华为")
console.log(hp1.rom)
console.log(hp2.ram)
function Test() {}
Test.prototype.name = "prototype"
let test = new Test()
console.log(test.name)
function Test() {}
Test.prototype.name = "prototype"
let test = new Test()
console.log(test.name)
二、更改原型
function Car() {
let this = {
__proto__: (Car.prototype = {
name: "Benz",
}),
};
}
function Car(){
this:{
__proto__: Car.prototype {
name:
}
}
}
- 不能通过被构造函数构造出的实例化对象更改原型
- 只能通过实例化对象访问到原型属性和方法
proto和prototype
__proto__是存prototype对象地址的地方,在new了一个实例之后,这个实例里会有__proto__属性
prototype是这个实例的祖先元素合集,它也是一个对象,里面存的东西就是这个实例的通用属性
constructor是在prototype里的一个属性,它默认会指向构造函数本身
__proto__和constructor可以更改为其他对象的地址
window和return
function test() {
let a = 1;
function plus1() {
a++;
console.log(a);
}
return plus1;
}
let plus = test();
plus();
plus();
plus();
(function () {
function Test() {}
window.Test = Test;
})();
三、原型和原型链
- 对象,除了把它构造出来的函数有原型,构造函数的原型都还有原型,且这个对象能继承它原型的原型的属性,这叫做原型链
- 所有的对象都有原型,包括原型本身
原型链
- 沿着
__proto__去找原型里的属性,一层一层去继承属性的链条
- 用实例来说明原型链
// 原型链
Professor.prototype.tSkill = "JAVA"
function Professor() {}
let professor = new Professor()
Teacher.prototype = professor
function Teacher() {
this.mSkill = "JS/JQ"
this.students = 500
this.success = {
alibaba: "28",
tencent: "30",
}
}
let teacher = new Teacher()
Student.prototype = teacher
function Student() {
this.pSkill = "HTML/CSS"
}
let student = new Student()
console.log(Professor.prototype)
// 可以一层一层往上继承
student.success.baidu = "100"
console.log(teacher, student)
//可以改或增加teacher.prototype的引用值属性,但不推荐这么做
student.students++
console.log(student, teacher)
// student501, teacher不变 原始值不能被子代修改
- 原型链的终点是
Object.prototype,它的__proto__是null
- 后代不能对上层的
prototype进行修改,只能访问
Object.create()
// 创建obj1空对象
let obj1 = Object.create(null)
console.log(obj1)
obj1.num = 1
let obj2 = Object.create(obj1)
console.log(obj2)
- 用
Object.create()可以指定创建对象的原型,和new一个实例化是一样的
- 如果用
Object.create()指定的原型是null那么这个对象是一个什么都没有的空对象,原型也没有
- 如果用
Object.create()指定原型,那这个对象可能不继承于Object.prototype(面试题)
四、包装类和隐式转换
let num = 1;
let obj = {};
let obj2 = Object.create(null);
document.write(num);
document.write(obj);
document.write(obj2);
- 上面的
obj能被页面渲染出来是因为obj这个对象继承原型的toString()方法,js会包装类,隐式执行toString()方法
obj2不能被页面渲染就是因为obj2的原型是空
重写方法
Number.prototype.toString.call(1);
Object.prototype.toString.call(1);
call/apply 更改this指向
function test() {
console.log("a");
}
test.call();
function Car(brand, color) {
this.brand = brand;
this.color = color;
}
let newCar = {};
Car.call(newCar, "Benz", "red");
console.log(newCar);
Car.apply(newCar, ["Benz", "red"]);
练习题
function Compute() {
this.plus = function (a, b) {
console.log(a + b);
};
this.minus = function (a, b) {
console.log(a - b);
};
}
function FullCompute() {
Compute.apply(this);
this.mul = function (a, b) {
console.log(a * b);
};
this.div = function (a, b) {
console.log(a / b);
};
}
let compute = new FullCompute();
五、课后作业
- 写一个插件,任意传两个数字,调用插件内部方法可进行加减乘除功能
(function () {
function Compute(opt) {
this.one = opt.one;
this.two = opt.two;
}
Compute.prototype = {
plus() {
console.log(this.one + this.two);
},
minus() {
console.log(this.one - this.two);
},
mul() {
console.log(this.one * this.two);
},
div() {
console.log(this.one / this.two);
},
};
window.Compute = Compute;
})();
let num = new Compute({
one: 4,
two: 2,
});
console.log(num.plus());
console.log(num.minus());
console.log(num.mul());
console.log(num.div());
function Car(opt) {
this.brand = opt.brand;
this.color = opt.color;
this.power = opt.power;
this.info = function () {
return (
"品牌为" +
this.brand +
",颜色为" +
this.color +
",排量为" +
this.power +
"的车"
);
};
}
function Person(opt) {
this.car = opt.car;
Car.call(this, this.car);
this.age = opt.age;
this.name = opt.name;
this.income = opt.income;
this.say = function () {
console.log(
"名字为" +
this.name +
",年龄为" +
this.age +
",收入为" +
this.income +
"的人买了一辆" +
this.info()
);
};
}
let bai = new Person({
name: "白境",
age: 20,
income: "20k",
car: {
brand: "Benz",
color: "white",
power: "3.0",
},
});
bai.say(); ;