JavaScript语言特点:除了对象什么也没有
函数 全局作用域 函数作用域 全局变量 局部变量
如果函数或其他数据类型,不依托非全局变量,那么就默认依托全局变量,作为全局对象的属性和方法,否则被当做局部对象属性或方法。this被用作指向属性和方法所依托的对象。
var x = 100;
var y=77;
var a1={
x:99,
xx:function(){
//var y=88; //如果注释这个变量,y将是全局变量的77
alert(y); //没有使用this指针,调用函数的对象无法影响y的值,函数运行时将从这里按作用域链逐级搜索取值
alert(this.x); //使用了 this 指针,调用函数的
}
}
a1.xx();//77, 99
a1.xx.call(window);//77, 100
//下面是重点!!!
var jj = a1.xx;
jj(); //77, 100 效果跟a1.xx.call(window); 一样
以上代码,倒数第三、四行代码都不难理解,倒数第一行代码怎么理解呢?首先我们看jj定义在全局对象中,即jj是window的属性,从jj的赋值我们知道,jj是一个方法,jj()也就相当于window.jj(),即调用函数的this指向全局对象window。
js中new操作符做了什么,请用代码解释
例:var obj = new Base(); 该步一共做了三件事:即 var obj = {}; obj.__proto__ = Base.prototype; Base.call(obj); 第一行,我们创建了一个空对象obj 第二行,我们将这个空对象的__proto__成员指向了Base函数对象prototype成员对象 第三行,我们将Base函数对象的this指针替换成obj。
var a= new A()
var a = {};
a.__proto__ = A.prototype;
A.call(a)
摘抄自js高级程序设计(第三版)145页:
要创建Person的新实例,必须使用new操作符。以这种方式调用构造函数实际上会经历以下4个步骤:
(1)创建一个新对象;
(2)将构造函数的作用域赋给新对象(因此this就指向了这个新对象);
(3)执行构造函数中的代码(为这个新对象添加属性);
(4)返回新对象。
构造函数会给创建的实例添加所有属性和方法包括自有属性和prototype的属性。
apply和call方法只会返回对象的自有属性,prototype属性都会丢弃。
function A(){
this.d=5;
this.c=5;
}
A.prototype.name="father";
var a= new A();//构造函数会给创建的实例添加所有属性和方法包括自有属性和prototype的属性
var b={};
A.call(b);//apply和call方法只会返回对象的自有属性,prototype属性都会丢弃
原型链概念:当构造器生成新对象,这个对象查找对象属性时,先找对象属性,如果没有则上溯到原型中查找,直到查找到object。对象自身属性优先级高于原型属性。可以覆盖。
JavaScript中的声明提前(hoisting),函数声明、变量声明提前
重点:js执行是从上到下,一行一行的,正式执行前,会将所有var声明的变量和function声明的函数,预读到作用域顶部。var 声明只是将声明提前,赋值仍然保留在原位置,function 声明,会将函数名称和函数体都提前。而且先预声明变量再预定义函数。这个过程叫“预解析”或者“预编译”。
console.log(a)//不会报错,输出undefined
var a=100
console.log(a)//100
var x=1,y=0,z=0;
var f=function(x){return x=x+1}
y=f(x)
function f(x){return x=x+3}
z=f(x)
console.log(x,y,z)
//1,2,2
解释:x只是作为参数传入函数,不变,
函数声明:以function开头,会先执行
函数表达式:var f=function(){}不提前
1. 函数声明提前,记录function f(){}
2. 函数表达式覆盖f var f = function(x){return x=x+1}
3. y=f(x);y 2
4. z=f(x);z 2
var a=1;
alert(a);//1
var f=function(){
a=2;
};
alert(a);//1
f();
alert(a);//2
function f(){
a=3;
}
alert(a);//2
f();//函数声明提前
alert(a);//2
f=function(){
a = 5;
};
alert(a);//2
f();
alert(a);//5
匿名函数
var num=1;
var myObject={
num:2,
add:function(){
this.num=3;
(function(){
console.log(this.num);//this指向window
this.num=4;
})();
console.log(this.num)
},
sub:function(){
console.log(this.num)
}
}
myObject.add();//1,3
myObject.sub();//3
在这个上下文(执行环境)中匿名函数并没有绑定到任何一个对象中,意味着this指向window