函数对象和数组对象都属于Object对象,Object对象是一个大的范围,而后两者是一个两种特别的对象
当传入的是 基本类型的参数时:就是复制了份内容而已
当传入的是引用类型的参数时: 复制的是引用类型参数的地址
原型链是用来查找属性的,除非去给原型链添加属性,否则设置对象的属性值是,不会去管原型链的事情
原型:
讲原型的时候,我们应该先要记住以下几个要点,这几个要点是理解原型的关键:
1、所有的引用类型(数组、函数、对象)可以自由扩展属性(除null以外)。
2、所有的引用类型都有一个’_ _ proto_ _'属性(也叫隐式原型,它是一个普通的对象)。
3、所有的函数都有一个’prototype’属性(这也叫显式原型,它也是一个普通的对象)。
4、所有引用类型,它的’_ _ proto_ _'属性指向它的构造函数的’prototype’属性。
5、当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,
那么就会去它的’_ _ proto_ _'属性(也就是它的构造函数的’prototype’属性)中去寻找。
6.任何对象都有一个constructor属性,指向创建此对象的构造函数
7.原型对象中的constructor属性,也指向函数对象的构造函数
原型链:
当试图得到一个对象的属性时,如果这个对象本身不存在这个属性,
那么就会去它构造函数的’prototype’属性中去寻找。
那又因为’prototype’属性是一个对象,即原型对象,所以它也有一个’_ _ proto_ _'属性。
例如:
// 构造函数
function Foo(name,age){
this.name=name;
this.age=age;
}
Object.prototype.toString=function(){
//this是什么要看执行的时候谁调用了这个函数。
console.log("I'm "+this.name+" And I'm "+this.age);
}
var fn=new Foo('小明',19);
fn.toString(); //I'm 小明 And I'm 19
console.log(fn.toString===Foo.prototype.__proto__.toString); //true
console.log(fn.__proto__ ===Foo.prototype)//true
console.log(Foo.prototype.__proto__===Object.prototype)//true
console.log(Object.prototype.__proto__===null)//true
首先,fn的构造函数是Foo()。所以:
fn._ _ proto _ _=== Foo.prototype
又因为Foo.prototype是一个普通的对象,它的构造函数是Object,所以:
Foo.prototype._ _ proto _ _=== Object.prototype
通过上面的代码,我们知道这个toString()方法是在Object.prototype里面的,
当调用这个对象的本身并不存在的方法时,它会一层一层地往上去找,一直到null为止。
所以当fn调用toString()时,JS发现fn中没有这个方法,于是它就去Foo.prototype中去找,
发现还是没有这个方法,然后就去Object.prototype中去找,找到了,就调用Object.prototype中的toString()方法。
这就是原型链,fn能够调用Object.prototype中的方法正是因为存在原型链的机制。
另外,在使用原型的时候,一般推荐将需要扩展的方法写在构造函数的prototype属性中,避免写在_ _ proto _ _属性里面。
解释:
JavaScript 执行在单线程上,所有的代码都是排队执行。
一开始浏览器执行全局的代码时,首先创建全局的执行上下文,压入执行栈的顶部。
每当进入一个函数的执行就会创建函数的执行上下文,
并且把它压入执行栈的顶部。当前函数执行完成后,当前函数的执行上下文出栈,并等待垃圾回收。
浏览器的 JS 执行引擎总是访问栈顶的执行上下文。
1、让外部访问函数内部变量成为可能
2、局部变量会常驻在内存中
3、可以避免使用全局变量,防止全局变量污染
4、会造成内存泄漏(有一块内存空间被长期占用,而不被释放)
变量f得到的是fn1返回的函数的地址值,fn3变量名被释放了,但是其所指向的地址又被f接收了,因此这块地址上的函数对象,没有成为垃圾对象被回收,还可以通过f进行调用
JS模块定义方式一:
把上面这段代码写到一个js文件中,在html页面加载这个js文件的时候,js文件中的代码会执行,然后调用返回得到返回值执行即可
JS模块定义方式二:
这样js文件加载,我们通过myMoudle2.属性名()就可以直接调用函数
原型链的继承要点: 将对应的父类型的实例对象变为子类型的原型对象
当实现了原型链继承效果后,子类型原型的constructor指向的是刚才的添加进原型链的Supper,我们需要让子类型的原型的constructor指向子类型
这里用call得到属性,可以不通过原型对象去调用属性,而是可以直接通过.去调用属性