平时没注意的常识:不写return的情况下: 普通函数默认返回值是undefined
而构造函数 实例化以后 默认返回this
一.原型链
沿着_proto_ 往上去找 原型的属性值的链条,称之为原型链
也就是说自己没有的属性,会到原型链里面去找祖先的属性
但是父辈不能找子辈的属性,这就是原型链的继承:
2.原型链的终点(面试基础)
原型链的终点是: Object.prototype
此时构造器指向系统自带的Object
2.1 原型的原型
前两种写法直接生成对象,构造器都指向系统自带的 原型链顶端的Object;
第三种使用自定义构造函数,此时构造器 指向 自定义的构造函数
原型的原型的构造器一定指向系统自带的Object
这样就能证明原型的原型是由系统自带的Object构造出来的:
3.通过原型链增加 父元素中的属性(面试基础)
给子元素赋值会改变父元素中的值
同时也能更改父元素中属性的值(仅仅引用值能改),但是不推荐使用这种方式去修改父元素的值
4.父辈中原始值属性不能更改(面试基础)
父辈中的原始值属性不能更改:
总结:父辈中:原始值不会被改变,引用值能被改变,改变方(如上式的student)都会被改变
5. this指向问题(面试基础)
谁调用this,this就指向谁:
实例化后car中属性为Benz , Car.prototype中属性为Mazda
二. create
用Object.create(对象,null) 构建对象和 new Obj () 效果一样
但是Object.create()提供了自定义原型的功能:
自定义原型:将test作为原型传进来:此时构造器还是指向Object (因为test是由Object创建出来的)
与obj1相反,此时obj2的构造函数指向obj
2 create
创建obj1空对象时 打印出什么属性都没有的空对象
增加属性obj1 = num
将obj1作为obj2的原型传进来,打印obj2:
从上所述:Object.create()有两个优点:
- 因为不是系统自带的,有些情况需要自定义prototype 时用Object.create()
- 把另外的对象作为 我这个对象的原型存在,从而达到继承,这样的形式更方便于查找
object.prototype 在顶端,是不是所有的对象都继承于它呢?
不是所有的对象都继承于Object.protyp! 由Object.create()创建的对象就不是
3. __prototype__只能是内置的,不能创造
自创的__proto__没有原型链的继承功能
4. toString()
undefined、null不能使用toString()方法:
console.log(undefined.toString());/报错
console.log(null.toString());/报错
var num = 1;
console.log(num.toString());/输出1
原因:原始值是没有属性的,硬要加属性就变成了包装类
数字对象中 toString()是内置的方法
undefined、null不能经过包装类转为对象,同时它们还也没有原型,不能去继承object、prototype
其实包装类就好比于 Object.create(Object.prototype)
5.原型方法的重写
系统内置的函数都有toString()方法:
对象类型的Number构造函数、对象类型的String构造函数······
原型方法的重写:
Object、Number两个类型的toString () 方法打印出来的结果不一样。
它们各自的prototype里面都有自己的toString()方法,并不是继承自Object.prototype:
如果Number里边没有toString()方法就会继承Object(因为Object是顶端的), 但是如果继承Object里面的话实现的功能就不对,不对的话就要对里面的方法进行重写。
所以实例化以后,他们的原型里面都保存了自己的toString():因为顶端的Object实现不了它想要的功能,所以系统在原型里面重新给它写了一个toString()
即它们各自的prototype里面都内置toString()方法,并不是继承自Object.prototype:
三. call和apply
call、apply能改变this指向
function test(){
console.log('a');
}
test(); /隐式的做了test.call();
apply:和call差不多,不过apply用的是数组
call/apply(函数名,实参)
apply能借用 别人写的方法:
直接apply(this),因为后面 compute
.plus()等调用它时,this指向plus
可以调用另一个函数里面的属性跟方法:
<script>
/ 把原先this改成目前里面的this,并且把this里面保存的属性和方法拿过来了, 目的
就是为了借用Teacher里面的属性和方法
function Teacher(name, age) {
this.name = name;
this.age = age;
}
function Student(name, age, hobby) {
Teacher.apply(this, [name, age]);
this.hobby = hobby;
}
var s = new Student('张三', '18', '电脑');
console.log(s);
/ 原先Teacher的方法并没有消失,还能继续使用
var t = new Teacher('ad', '17');
console.log(t);
/所以apply、call只是在自己的函数里面调用另一个函数的方法、属性
</script>
实战
两个构造函数 :
function Car(){}
function Person(){}
利用call、apply 将这两个合并在一起
可设置车的品牌、颜色、排量,再写一个构造消费者的函数,设置用户的名字、年龄、收入,通过选择的方法实例化该用户喜欢的车,再设置车的属性。