什么是作用域?原生链?它们的区别是什么?
var a=1;
function b(){
var a=2;
function c(){
var a=3;
console.log(a)
}
c();
}
b();//3
一、作用域链
作用域是相对于变量来说的。如
全局作用域==>函数b作用域==>函数c作用域;
作用域的特点是现在自己的变量范围中查找,如果找不到就会沿着作用域往上找。
例:执行c()时,若c中没有变量a,则会向上找,直到找到a,这个查找的过程就叫作用域链。
二、原生链
①prototype 每一个函数都有这个属性,这个属性指向函数的原型对象
function Person(){
this.name=name; }
Person.prototype.name='babilong'
var person=new Person();
console.log(person.name);
函数的prototype指向一个对象,而这个对象正是调用构造函数时创建的实例的原型。
每一个对象(除null)创建的时候都有一个原型,都会从原型中继承属性。
②__proto__ 每一个对象都会有的属性,这个属性会指向该对象的原型。
function Person(){ };
var person=new Person();
person.__proto__=Person.prototype//true
③构造函数 每一个原型都有一个constructor属性,指向该关联的构造函数。
person.constructor===Person.prototype.constructor
person本身没有,但是它的原型Person.prototype有constructor属性。Person
④原型链
每一个构造函数都有一个原型对象,原型对象那个都包含一个指向构造函数的指针(constructor),而实例都包含一个指向实例原型的内部指针(__proto__),这个原型对象还可以有自己的原型,以此类推,就形成了一个原型链,直到找到某个属性时。先去这个对象里找,如果没有就去原型对象里面找,如果还是没有就去原型对象的原型对象中找。
三、原型链的继承
核心:父类的实例就是子类的原型。
function Father(){ this.name=name||"张三",
this.play=function(){};
}
//原型方法
Father.prototype.say=function(){
}
function Son(){}
//父类的实例就是子类的原型
Son.prototype=new Father();
var son =new Son();
//继承
son.play();
son.say();
优点:①子类的实例也是父类的实例
②父类新增原型方法/原型属性,子类都能访问的到。
缺点:①子类新增的方法和属性,必须在new父类()之后,不能放在构造器中。
②无法是实现多继承。
③来自原型对象的引用属性是所有实例共享的。
④创建子类实例时,无法向父类传参。