JS作用域与new关键字——长期更新

关于作用域: 

首先要知道js的两点,一是变量提升,而是js只有词法作用域。下面三段代码可以很好诠释这个逻辑。

//************************************************************************** 
var a="aa"; 
function test(){ 
alert(a);//undefined,函数执行后,在函数环境内,var a会预解析,当弹出a时,首先先找本层环境内有无声明,发现有但是代码没有执行到赋值,所以结果是undefined。 
var a="bb";//var a会预解析在函数开头,执行到这行才进行赋值 
alert(a);//“bb” 
} 
test(); 
alert(a);//”aa” 找全局环境下的声明,找到了var a=”aa”

//************************************************************************** 
var a="aa"; 
function test(){ 
alert(a);//“aa”,函数执行后,在函数环境内,没有找到本层环境关于a的声明,所以开始向上一层环境查找。 
a=”bb”;//执行到这行开始改变全局a的量 
} 
test(); 
alert(a);//”bb” 全局环境的a在函数执行时已经被改变

//************************************************************************** 
function test(){ 
b();//函数b会被预解析,因此可以调用,执行了输出1; 
var a=1; 
function b(){ 
console.log(1); 
console.log(a);//undefined 
var a=2; 
} 
} 
test();

//先找本层环境有无声明,有的话,看是否进行了赋值;只有声明没有执行赋值,就是undefined.没有声明也没有赋值的话,就再向上一层查找,直到找到为止.如果所有的执行环境都没有找到,那么控制台就会报错变量找不到.

关于new关键字: 

js中提供多个內建对象(string、number、array、math、date等,但是前三个不建议使用,能不用就别用)和自定义对象。在创建对象时,一般使用new关键字。也有人建议用对象字面量来创建对象。对象字面量的形式好理解,今天说一说new关键字。依然就一段代码来说,原作者是:hebedich,来源:脚本之家。

function Animal(name){ 
this.name = name; 
} 
Animal.color = “black”; 
Animal.prototype.say = function(){ 
console.log(“I’m ” + this.name); 
}; 
var cat = new Animal(“cat”);

console.log( 
cat.name, //cat 
cat.height //undefined 
); 
cat.say(); //I’m cat

console.log( 
Animal.name, //Animal 
Animal.color //back 
); 
Animal.say(); //Animal.say is not a function 

代码解读:1-3行创建了一个函数Animal,并在this上定义了属性:name,name是值是被执行的形参。 
第4行在Animal对象上定义了一个静态属性:color,并赋值black 
5-7行在Animal函数的原型对象prototype上定义了一个say方法,say方法输出了this的name值 
8行通过new关键字创建了一个新对象cat 
10-14行cat对象尝试访问name和color属性,并调用say方法 
16-20行Animal对象尝试访问name和color属性,并调用say方法

重点是第八行new Animal的代码,js引擎在执行这句代码时,做了很多工作,用伪代码来表示其工作流程 

var obj = {}; 
obj.proto = Animal.prototype; 
var result = Animal.call(obj,”cat”); 
return typeof result === ‘obj’? result : obj; 

1、创建一个空对象 
2、把obj的proto指向Animal的原型对象prototype,此时即创建了原型链obj(cat)-Animal.prototype-Object.prototype-null 
3、在obj对象执行空间调用Animal函数并传入参数cat。相当于var result = obj.Animal(”cat”) 
4、返回值

我相信大家还有一个疑惑的地方也许跟我一样,为啥Animal.name的结果是Animal。什么鬼 
原来函数对象在产生时会内置name属性并将函数名作为赋值(仅函数对象) 
那为什么Animal.say不存在呢 
我们看下Animal的原型链:Animal-Function.prototype-object.prototype-null

js引擎总是这样,先在局部作用域查找属性或者方法,当找不到的时候沿着原型链进行查找,直到null。 
js中new关键字的主要作用是继承,而继承的方式则是原型链,上面的例子中,cat对象在产生时便继承了Animal中 定义的方法和属性,因此cat不是Animal的实例而是其子类。

js中使用new关键字和对象字面量的区别: 
使用new关键字以原型的方式将user对象暴露在window对象中 

//one 
var user = function(){ 
this.name=”“; 
this.id=”“; 
}; 
user.add = function(){ 
console.log(“add”); 
}; 
user.delete = function(){ 
console.log(“delete”); 
}; 
user.prototype = user; 
window.user = new user();

不使用new关键字直接将user暴露在window对象中 

//two 
var user = { 
name:”“, 
id:”” 
}; 
user.add = function(){ 
console.log(“add”); 
}; 
user.delete = function(){ 
console.log(“delete”); 
}; 
window.user = user;

//******************************************************************************************
function Animal(nae){ 
this.nae = nae; 
} 
Animal.color = “red”

var cat = new Animal(“cat”);

console.log( 
Animal.color, //red 
Animal.name, //Aniaml 
cat.nae //cat 
);


ps:8/8重编辑














评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值