
一开始Person函数实例化的时候,就已经把"lingyuanqiang"传递给参数name,把29传递给参数age,也就是说这时候name="lingyuanqiang",age=29。所以当执行getName方法时返回的就是name,也就是"lingyuanqiang"。而当执行setName方法后,就把"liuhuan"重新赋值给name,这个时候name="liuhuan",age=29。
局部变量和全局变量同名时,会隐藏这个全局变量;
4变量
关键字: 4变量
41 变量的类型
JS是松散类型的语言
42 变量的声明
var 声明是变量的标准声明
var 声明的变量是永久性的,不能用delete运算符删除
全局对象,调用对象初始化时,JS解析器会在相应的代码段里寻找var声明的变量,
然后在全局对象,调用对象中创建相应的属性,此时它是未赋值的(undefined),
当程序执行到相应的var声明代码段时才会给相应对象的属性赋值
重复的声明:根据以上var声明作用的理解,重复的var声明不会造成任何错误,
var声明只是方便创建全局对象,调用对象的属性,代码只是赋值用的
遗漏的声明:给未声明的变量赋值,JS会隐式声明全局变量(在全局对象中增加相应的属性),然后给其赋值
43 变量的作用域
全局变量,局部变量
局部变量和全局变量同名时,会隐藏这个全局变量
431 没有块级作用域
函数中声明的变量,无论在哪里声明的,在整个函数中它们都是有定义的
432 未声明的变量和未赋值的变量
alert(u);会产生一个错误--使用未声明的变量会产生一个错误
var u;alert(u);会跳出undefined---使用未赋值的变量,使用的它的默认值undefined
44 基本类型和引用类型
第三章已经讲过
45 垃圾收集
同java
46 作为属性的变量
461 全局对象
JS解释器开始运行时,在执行任何JS代码前,会创建一个全局对象,这个对象的属性就是JS全局变量,
并初始化为undefined
var声明一个JS全局变量时,实际上就是定义了一个全局对象的属性,
JS解释器还会用预定义的值和函数来初始化全局对象的许多属性,如:Infinity parseInt Math
非函数内部可以用this来引用这个全局对象
客户端的JS中,Window对象代表浏览器窗口,它包含该窗口中的所有JS代码的全局对象,具有自我引用的window属性
462 局部变量:调用对象
函数的局部变量存放在调用对象的属性
调用对象是一个完全独立的对象,所以可以防止覆盖同名的全局变量
463 JS的执行环境
JS解释器执行一个函数时,会创建一个执行环境
JS允许同时存在多个全局执行环境,如:JS客户端的ifame的情况
47 深入理解变量作用域
每个JS执行环境都有一个和它相关联的作用域链它是一个对象列表或对象链
查询x:变量名解析(variable name resolution)的过程,它开始查看作用域链的每一个对象,
如果有,返回值,如果没有继续查询下一个对象,以些类推
作用域链的优先级:嵌套函数的调用对象>调用对象>全局对象
根据以上理解说明JS初始化的过程:
在JS解释器执行任何代码之前,创建全局对象
用预定义的值和函数来初始化全局对象中的属性,egMath,Infinity,parseInt
搜索函数外的var声明,创建全局对象相应的属性,初始化为undefined
创建全局的执行环境,作用域链只有一个对象-全局对象
依次执行代码
遇到var声明赋值语句给全局对象相应的属性赋值
遇到未声明赋值语句,在全局对象中增加相应的属性,并赋值
遇到函数调用,创建调用对象
搜索函数中的var声明和参数,创建调用对象相应的属性,初始化为undefined
创建函数执行环境,作用域链--第一对象:调用对象;第二对象:全局对象
依次执行代码
遇到var声明赋值语句给调用对象相应的属性赋值
遇到未声明赋值语句,在全局对象中增加相应的属性,并赋值
遇到函数调用,创建嵌套函数的调用对象
搜索嵌套函数中的var声明和参数,创建嵌套函数的调用对象相应的属性,初始化为undefined
创建嵌套函数执行环境,作用域链--第一对象:嵌套函数的调用对象;第二对象:调用对象;第三对象:全局对象
依此类推
eg1
var scope="global";
function f(){
alert(scope);
var scope="local";
alert(scope);
}
f();
过程:
创建全局对象,搜索函数外的var声明语句,在全局对象中创建scope属性,scope=undefined
创建全局的执行环境,作用域链只有一个对象:全局对象
依次执行代码:
var scope="global"时,变量名解析开始,在全局对象属性中查找scope属性
把"global"赋给scope
遇到函数调用:创建调用对象
搜索函数中的var声明语句和参数,在调用对象中创建scope的属性,scope=undefined
创建函数执行环境,作用域链:调用对象>全局对象
依次执行代码:
alert(scope),查询scope,变量名解析,先搜索调用对象,找到scope属性,其值为undefined,执行
var scope="local",查询scope,变量名解析,先搜索调用对象,找到scope属性,scope="local"
alert(scope),查询scope,变量名解析,先搜索调用对象,找到scope属性,其值为"local",执行
eg2
var scope="global";
function f(){
alert(scope);
scope="local";
alert(scope);
}
f();
过程:
创建全局对象,搜索函数外的var声明语句,在全局对象中创建scope属性,scope=undefined
创建全局的执行环境,作用域链只有一个对象:全局对象
依次执行代码:
var scope="global"时,变量名解析开始,在全局对象属性中查找scope属性
把"global"赋给scope
遇到函数调用:创建调用对象
搜索函数中的var声明语句和参数,没有找到var声明语句
创建函数执行环境,作用域链:调用对象>全局对象
依次执行代码:
alert(scope),查询scope,变量名解析,先搜索调用对象,没找到scope属性,再搜索全局对象,找到scope属性,其值为"global"执行
scope="local",查询scope,变量名解析,先搜索调用对象,没找到scope属性,,再搜索全局对象,找到scope属性,scope="local"
alert(scope),查询scope,变量名解析,先搜索调用对象,没找到scope属性,再搜索全局对象,找到scope属性,其值为"local",执行
eg3
scope1="global";
alert(scope1);
function f(){
alert(scope2);
scope2="local";
}
f();
过程:
创建全局对象,没有找到var声明语句,没有自定义的全局对象属性
创建全局的执行环境,作用域链只有一个对象:全局对象
依次执行代码:
scope1="global"时,变量名解析开始,作用域链是没有找到scope1属性,在全局对象属性中创建scope1属性,并赋值为"global"
alert(scope1)时,变量名解析开始,作用域链是找到scope1属性,其值为"global",执行
遇到函数调用:创建调用对象
搜索函数中的var声明语句和参数,没有找到var声明语句
创建函数执行环境,作用域链:调用对象>全局对象
依次执行代码:
alert(scope2),查询scope2,变量名解析,作用域链是没有找到scope2属性,报错scope2 is not defined
例:
function square(num){
total=numnum; //这是 *** 作全局变量。
return total;
}
val total=50;
val number=square(20);
alert(total);//total的值变成了400。
这些代码将导致全局变量total的值发生变化。
把这个函数写成这样才是正确的:
function square(num){
var total=numnum;
return total;
}
又如:
<script>
var cookie="i am cookie";
function test(){
var cookie="i am not fei cookie";//定义局部变量的值,test函数执行后不会影响到全局的cookie
}
test();
documentwrite(cookie);
</script> //////////// 输出 i am cookie
去掉test()函数中变量var 如下:
<script>
var cookie="i am cookie";
function test(){
cookie="i am not fei cookie";//修改全局变量的值
}
test();
documentwrite(cookie);
</script>//////test函数执行后输出 i am not fei cookie
在函数中并且不加var 如何改变全局变量?如下:
<script>
var cookie="i am cookie";
function test(){
var cookie="i am not fei cookie";//定义局部变量的值,test函数执行后不会影响到全局的cookie
windowcookie=cookie; ///第一个cookie是全局的函数外部定义的,后面的cookie是在函数内定义的
}////利用window.变量
test();
documentwrite(cookie);
</script> /////输出 i am not fei cookie
要在方法1中 访问 方法2的变量。
必须借助于 全局变量。
在方法2中 *** 作全局变量 windowcookie=cookie;
这时全局变量被 改变。
在这方法一 中去访问。
例
var total;
square();
square1();
function square(){
total='aaaa';
}
function square1(){
alert(total);
}
从语法来说,函数名大小写没有限制。
不过遵守一些规则会让代码更加规范。
举个例子,
函数开头最好用小写,而且用动词开头,比如
setName()
getName()
如果程序有很多模块组成,模块内的私有函数最好用 _ 开头,比如
_setName()
_getName()
命名规则因人而异,没有统一的标准,以上只是个参考。
1 $render用处就是:
在$viewValue改变的时候可以重新绑定model数据,主要使用在自定义指令的时候,但是我们要注意一点在$viewValue改变的时候可以重新绑定model数据,
但是我们要注意一点($viewValue和DOM节点的value是不同的),我觉得他们的区别有点类似setTimeout和$timeout的区别,但是又不太一样。
ps:其实modelValue和绑定的数据也可以不同
2ngModelController则是ng-model指令中所定义的controller,
在ngModelController中有两个很重要的属性,一个叫做$viewValue,一个叫做$modeValue。
$viewValue:指令渲染模板所用的值,$viewValue属性保存着更新视图所需的实际字符串
$modeValue:指控制器中流通的值,modelValue由数据模型持有。$modelValue和$viewValue可能是不同的,取决于$parser流水线是否对其进行了 *** 作。
于此相关的另外两个指令:$parses和$formatters
$parses的作用是:将$viewValue->$modelValue
$formatters的作用是:将$modelValue->$viewValue
3$apply的作用: $apply()函数可以从Angular框架的外部让表达式在Angular上下文内部执行,Scope提供$apply方法传播Model的变化。
在apply()方法里面,它会去调用scopedigest()方法,apply()方法带一个函数或者一个表达式,然后执行它,
最后调用scopedigest()方法去更新bindings或者watchers。
$apply()方法可以在angular框架之外执行angular JS的表达式。
在$apply方法中提到过脏检查,首先apply方法会触发evel方法,当evel方法解析成功后,会去触发digest方法,digest方法会触发watch方法
scopedigest(): 用于检查绑定的数据到底有没有发生变化。
4watch方法用法:
语法:
$watch(watchFn,watchAction,deepWatch)
三个参数:
watchFn:angular表达式或函数的字符串
watchAction(newValue,oldValue,scope):watchFn发生变化会被调用,是一个函数
deepWatch:可选的布尔值命令检查被监控的对象的每个属性是否发生变化
$watch会返回一个函数,想要注销这个watch可以使用函数,true/false
5angularJS——自定义服务provider之$get
可以认为provider有三个部分:
第一部分是私有变量和私有函数,这些变量和函数会在以后被修改。
第二部分是在appconfig函数里可以访问的变量和函数,所以,他们可以在其他地方使用之前被修改。注意,这些变量和函数一定要添加到this上面才行。
第三部分是在控制器里可以访问的变量和函数,通过$get函数返回。
当使用 provider创建服务的时候,唯一可以让控制器访问的属性和方法是在$get()函数里返回的属性和方法。
使用Provider的优点就是,你可以在Provider对象传递到应用程序的其他部分之前在appconfig函数中对其进行修改。
当你使用Provider创建一个service时,唯一的可以在你的控制器中访问的属性和方法是通过$get()函数返回内容。
大型数据进行访问的时候许多大型互联网站都是为全球用户提供服务的,
用户分布范围广,各地网络情况千差万别。在国内,还有各个运营商网络互通难的问题。
使用在具体的环境中,
6angularjs中的run()方法使用
run方法用于初始化全局的数据,仅对全局作用域起作用。
例子:
<script type="text/javascript">
var m1 = angularmodule('myApp',[]);
m1run(['$rootScope',function($rootScope){
$rootScopename = 'hello';
}]);
consolelog( m1 );
</script>
7config方法
在模块加载阶段,对模块进行自定义配置
config可以注入$stateProvider, $urlRouterProvider, $controllerProvider, $provide, $httpProvider等等provider,
config的工作流程:
新建一个模块,这个模块中有一个服务,一个自定义指令
8$routeProvider
$routeProvider是一个用于配置路由的内置服务。
它主要有以下两个成员函数:
otherwise(params):设定映射信息到$routecurrent,一般用于指定没有标明的路由如何处理。
when(path, route):向$route服务添加新的路由。path是指定的URL路径,route标明路由的处理。
9ng-view是由ngRoute模块提供的一个特殊指令,它的独特作用是在HTML中给$route对应的
视图内容占位
$routeProvider是组网址的配置,将它们映射相应的HTML页面或 ng-template,并附加一个控制器使用相同键的服务
$routeProviderwhen('/',{template:'这是首页页面'})
10template 和 templateUrl
template: '<div><h2>Route</h2></div>'
AngularJS会将配置对象中的HTML模板渲染到对应的具有ng-view指令的DOM元素中。
templateUrl: 'views/template_namehtml'
应用会根据templateUrl属性所指定的路径通过XHR读取视图(或者从$templateCache中读取)。
如果能够找到并读取这个模板,AngularJS会将模板的内容渲染到具有ng-view指令的DOM元素中。
11在组件中注入服务
Angular在底层做了大量的初始化工作,这极大地降低了我们使用依赖注入的成本,
现在要完成依赖注入,我们只需要三步:
第一步:通过import导入被依赖的对象服务
第二步:在组件中配置注入器。在启动组件时,Angular会读取@Component装饰器里的providers元数据,
它是一个数组,配置了该组件需要使用的所有依赖,Angular的依赖注入框架会根据这个列表去创建对应的示例。
第三步:在组件构造函数中声明需要注入的依赖。注入器会根据构造函数上的声明,
在组件初始化时通过第二步中的providers元数据配置依赖,为构造函数提供对应的依赖服务,最终完成依赖注入。
例如:
// appcomponentts
// 1 导入被依赖对象的服务
import { MyService } from '/my-service/my-serviceservice';
// 2 在组件中配置注入器
@Component({
providers: [MyService]
})
export class AppComponent {
// 3 在构造函数中声明需要注入的依赖
constructor(private myService: MyService) {}
}
12在服务中注入服务
例如:
// powerservicets
import { Injectable } from '@angular/core';
@Injectable()
export class PowerService {
// power come from here
}
// countservicets
import { Injectable } from '@angular/core';
import { PowerService } from '/power/powerservice';
@Injectable()
export class CountService {
constructor(private power: PoowerService) {}
}
// appcomponentts 这里是当前组件,其实模块中的注入也一样,后面讲到
providers: [
CountService,
PowerService
]
这里需要注意的是@Injectable装饰器是非必须的,因为只有一个服务依赖其他服务的时候才必须需要使用@Injectable显式装饰,
来表示这个服务需要依赖,所以我们的PowerService并不是必须加上@Injectable装饰器的,
可是,Angular官方推荐是否依赖其他服务,都应该使用@Injectable来装饰服务。
13在模块中注入服务
在模块中注册服务和在组件中注册服务的方法是一样的,只是在模块中注入的服务在整个组件中都是可用的。
例如:
// appmodulets
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from '/appcomponent';
@NgModule({
declarations: [
AppComponent,
],
imports: [
BrowserModule
],
providers: [CountService, PowerService],
bootstrap: [AppComponent]
})
export class AppModule { }
与在组件中注入不同的是,在Angular应用启动的时候,它好首先加载这个模块需要的所有依赖,
此时会生成一个全局的根注入器,由该依赖创建的依赖注入对象会再整个应用中可见,并共享一个实例。
14Provider
Provider一个运行时的依赖,注入器依靠它来创建服务对象的实例。
通常下, 函数内的一切都是局部的,私有的, 外面怎么能调用到呢
<script type="text/javascript">function a() {
thistb = function( s ) {
alert( s );
}
}
var b = new a();
btb( 222 ); //这样才行啊
</script>
欢迎分享,转载请注明来源:内存溢出
微信扫一扫
支付宝扫一扫
评论列表(0条)