原型链
函数对象都有自己的原型。
function Car() { }
var car = new Car();
console.log(Car.prototype);//构造函数Car的原型
console.log(car);
//原型链 car.__proto__.__proto__
沿着proto 这个链条网上找属性的链条就是原型链
实例化对象不可以修改原型上的原始值。??? car.proto.age =13;
- 如果原型上的属性是原始值类型。那么实例化对象就会将原型上的属性添加到自身。并且赋值。 ```javascript /**原始值不可以修改*/
function Professor() { }
Professor.prototype.tSkill = “Java”;//将Professor原型上的tSkill 赋值为Java;
var professor = new Professor();
// professor = {
// proto:{
// constructor:Professor(),
// tSkill:’Java’
// }
// }
Teacher.prototype = professor;//将Teacher的原型上赋值为professor这个实例化对象; // teacher={ // mSkill:’JS/JQ’, // proto: { // proto:{ // constructor:Professor(), // tSkill:’Java’ // } // } // } function Teacher() { this.mSkill = “JS/JQ”;//如果不new或者执行。this就没有任何意义。new的情况下 mSkill 就变成了实例化对象的一个属性. } var teacher = new Teacher();//实例化Teacher这个构造函数,new之后this指向teacher
Student.prototype = teacher;//将Student的原型赋值为teacher这个实例化对象
function Student() { this.pSkill = “HTML/CSS”;//同上。 } var student = new Student();
console.log(student); //修改原始值。 student.mSkill = ‘Python’; //如果student要修改老师的mSkill,因为修改的是原始值。 //则会访问到teacher中的mSkill 给自己再添加一个相同的属性和值。
// student:{ // pSkill:’HTML/CSS’, // mSkill: ‘Python’ // proto:{ // mSkill:’JS/JQ’, // proto: { // proto:{ // constructor:Professor(), // tSkill:’Java’ // } // } // } // }
![image.png](https://cdn.nlark.com/yuque/0/2021/png/12831495/1617076080650-1c633418-82e2-4469-b86c-60280b6c7811.png#crop=0&crop=0&crop=1&crop=1&height=122&id=H7GsE&margin=%5Bobject%20Object%5D&name=image.png&originHeight=122&originWidth=354&originalType=binary&ratio=1&rotation=0&showTitle=false&size=8097&status=done&style=none&title=&width=354)
<a name="oUa1s"></a>
#### 实例化对象可以修改原型上的引用值。
1. 实例化对象直接就可以修改原型上的引用值。
```javascript
/********************************************引用值可以修改*****************************************************/
function Professor() {
}
Professor.prototype.tSkill = 'Java';
//在Professor 原型上添加tSkill;
var professor = new Professor();
//实例化professor
Teacher.prototype = professor;
//Teacher的原型赋值为professor
function Teacher(){
this.mSkill = 'JS/JQ';
this.success ={
'ali':100,
'baidu':200,
'tencent':90
}//success 是引用值。
}
var teacher = new Teacher();
Student.prototype = teacher;
//Student的原型赋值为teacher
function Student(){
this.pSkill = 'HTML/CSS';
}
var student = new Student();
console.log('before', student);
//修改之前student
student.success.baidu = 100;
//将student原型上的success.baidu修改为100;
console.log('after', student);
//修改之后student sucess.baidu 从200变成100;
this指向
function Car(){
this.brand = 'Benz';
}
Car.prototype={
brand:'Mazda',
intro:function(){
console.log('我是'+ this.brand +'车');
}
}
// 我是Mazda车;对象内部this就指向对象本身。
Car.prototype.intro();
//实例化 car
var car = new Car();
//我是Benz车
car.intro();
function Person(){
this.smoke = function(){
this.weight--;
}
}
Person.prototype={
weight:130
}
//将person 原型赋值为一个新对象
var person = new Person();
// 实例化一个person对象
person.smoke();
//此时person会从Person的原型上读取weight属性。
//因为weight是原始值类型、所以把这个属性添加到自身。赋值为129
console.log(person);
console.log(Person.prototype);//130
对象
创建方法
- var obj ={};
- var obj = new Object();
原型也是对象,原型的原型是由系统默认的Object构造出来的
function Obj() {
}
var obj = new Obj();
//obj.__proto__===Obj.prototype true
console.log(obj.__proto__);
对象的方法
Object.create
_
function Obj() { };
//构造函数的原型上定义一个num赋值为3。
Obj.prototype.num = 3;
//以Obj.prototype为原型创建了obj1 obj1的原型和
var obj1 = Object.create(Obj.prototype);
//实例化obj2
var obj2 = new Obj();
/*new 的作用。
实例化了obj2
调用构造函数Obj的初始化属性和方法。
指定实例对象的原型
*/
//obj1的原型和obj2的原型完全相等
console.log(obj1.__proto__ === obj2.__proto__); //true;
var obj1 = Object.create(null);
//将obj1的原型赋值为null;
obj1.num = 1;
//obj1添加了一个num属性。
var obj2 = Object.create(obj1);
//以obj1为原型创建了obj2;
console.log(obj2);
// {
// __proto__: obj1 -> {
// name: 1
// }
// }
console.log(obj2.num);//1
toString
- undefined,null 不能经过包装类。所以不能继承Object 的属性和方法
- number有string因为有包装类 ```javascript var num = 1;
num.toString(); //由于1是没有toString 方法。所以只能先转成包装类。new Number(num)->toString()
var num2 = new Number(num);
document.write(num2); //这document.write会隐式把num2 转换成string;
3. 重写toString方法
```javascript
Object.prototype.toString.call('1')
"[object String]"
Object.prototype.toString.call(1)
"[object Number]"
Object.prototype.toString.call(true)
"[object Boolean]"
Object.prototype.toString.call(undefined)
"[object Undefined]"
Object.prototype.toString.call(null)
"[object Null]"
Object.prototype.toString.call(function(){})
"[object Function]"
Object.prototype.toString.call({name:1})
"[object Object]"
Object.prototype.toString.call([1,2,3])
"[object Array]"
call/apply更改this指向
function test(){
console.log(1);
}
test();//test.call() 调用函数时。系统隐式增加了.call;
例子
//加减计算方法
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);//apply 更改了Compute 类的指向。
//乘
this.mul = function(){
console.log(a*b);
},
//除
this.div = function(){
console.log(a/b);
}
}
//实例化FullCompute
var compute = new FullCompute();
compute.plus(1,2);//3
compute.minus(1,2);//-1
compute.mul(1,2);//2
compute.div(1,2);//0.5
demo
年龄为多少岁姓名为xx买了一辆排量为xx的什么颜色,什么牌子的汽车。
//Person的构造函数。
function Person(opt){
Car.call(this,opt.carOpt);//这里借用了Car 修改了car的this指向。此时this指向实例化对象。
this.name = opt.name;
this.age = opt.age;
this.speak = function(){
console.log(this.name +''+this.age +'岁 '+'买了一辆排量为'
+this.dispatchment
+this.color+'颜色的'
+this.brand+'汽车')
}
}
//Car的构造函数
function Car(opt){
this.color = opt.color;
this.brand = opt.brand;
this.dispatchment = opt.dispatchment
}
//实例化Person
var p = new Person({
name:'张三',
age:30,
carOpt:{
color:'red',
brand:'Benz',
dispatchment:'3.0T'
}
});
console.log(p)//{name:'张三',age:30,color:'red',brand:'Benz'}
p.speak();