`

JS 学习总结

 
阅读更多
1.call、apply的使用
语法

function.call(thisObj,param1,param2,param3...);
function.apply(thisObj,[param1,param2,param3...]);

用法是改变function的作用域,将参数的上下文作用域修改成thisObj对象, 也可以说this对象为thisObj.
默认的function的作用域是window,this相当于window.function
--------------------------------------------------------------------------------------------------------------------
2.函数的定义方式:

1.function xxx(){}
2.var xx = function(){}
3.var test3 = new Function("a","b","return a+b;");//不常用,定义在方法内也是顶级作用域

第一种和第二种方式基本一致,除了第二种解析方式是顺序解析,需要在调用的方法前定义。

以上typeof()测试皆为function
--------------------------------------------------------------------------------------------------------------------
3.对象定义方式
1.var obj = {};//空对象,没有任何属性和方法
obj.xx = "123";
obj.function = function(){};

2.通过function 构造函数或者工厂模式来创建

function createPerson(name,sex,age){  
    var obj = {};  
    obj.name = name;  
    obj.sex = sex;  
    obj.age = age;  
    return obj;  
} 


var obj1 = createPerson("anker","男",16);
typeof(createPerson); //function
typeof(obj1); //object


function Person(name,age,sex){  
    this.name = name; //this关键字指向new的对象  
    this.age = age;  
    this.sex = sex;  
    this.say = function(){  
        alert(this.name);  
    }  
}  

var obj2 = new Person("anker","男",16);
typeof(Person); //function
typeof(obj2); //object

这里不要把对象和function进行混淆,对象是需要通过{}或者new方式来创建,function只是提供创建对象的一个模板或者工厂。

3.1  对象的引用传递

var person={name:'anker',age:100};
var x = person;
x.age = 19;
console.log(x.age);//19
console.log(person.age);//19
说明js中对象的赋值也是采用引用的方式,同时指向同一个对象。

function changebj(obj)  {obj.age = 10};
changebj(person);

console.log(person.age);

10//打印结果也是10,说明函数传递的也是对象的引用。修改的是同一个对象。

person.sex = '男';//若该属性不存在则添加,若存在则覆盖。

访问对象的方式:

obj.name
obj["name"]或者obj['name']//必须采用双引号或者单引号括起来

--------------------------------------------------------------------------------------------------------------------
4.匿名函数
(function(){//代码 })();  //可立即执行的匿名函数

解释:,包围函数(function(){})的第一对括号向脚本返回未命名的函数,随后一对空括号立即执行返回的未命名函数,括号内为匿名函数的参数。  
例子:(function(arg){ alert(arg+100); })(20); 
这个例子返回120。

1.匿名函数,就是没有引用直接加上()进行执行的函数。


var addFunc = function(a,b){
 cosole.log(a+b);
};
--调用方式
addFunc(1,2);


--匿名函数
(function(a,b){console.log(a+b)})(1,2);

上面两个函数的产生的结果是一样的.只不过addFunc为函数对象的引用,而匿名函数不存在引用.

--来看个复杂的利用匿名函数的例子

var add = (function(){
	var sum = 0 ;
	return function(){
		for(var i=0;l=arguments.length,i<l;i++){
			sum+=arguments[i];
		}
		return  sum;
	};
})(); --加上括号为匿名函数的写法,可以理解为直接执行了此函数,函数的执行结果返回

add(1,2,3,4);
add(2);
--等价于
var func1 = function(){
	var sum = 0 ;
	return function(){
		for(var i=0;l=arguments.length,i<l;i++){
			sum+=arguments[i];
		}
		return  sum;
	};
};
var add = func1();
add(1,2,3,4);
add(2);


//现在有一个场景,需要设计一个函数,前面每次调用,不会真正去计算,而是把参数保存下来,等到需要计算的再一起计算

var currying = function(fn){
	var args = [] ;
	return function(){
		if(arguments.length === 0){
			return fn.apply(this,args);
		}else {
			Array.prototype.push.apply(args,arguments);
			return arguments.callee;
		}
	};	
}
var add = (function(){
	var sum = 0 ;
	return function(){
		for(var i=0;l=arguments.length,i<l;i++){
			sum+=arguments[i];
		}
		return  sum;
	};
})();

var add  = currying(add);
add(1);
add(2);
add(3);

add();
---------------------------------------------------------------------------------------------------------------------
5.闭包
可以理解成一个函数内的内部函数,它被创建在一个函数内部,引用这其外部函数的变量值。


var a = function(){
  var x = 1;
  return function(y){
	console.log(x+=y);//外部函数的x值就被包裹在引用对象中
  }
}

var b = a();//实际上是返回function(y){...}的引用
b();//执行上面的引用,此时的x值变成了private的属性
闭包的两个作用:
1.可以读取函数体所在外部函数的局部变量
2.就是让这些变量的值始终保持在内存中

------------------------------------------------------------------------------------------------------------------------
6.constructor

constructor 属性返回对创建此对象的数组函数的引用。
var test=new Array();

if (test.constructor==Array)//判断test的构造函数是否是Array
{
document.write("This is an Array");
}


var createPerson = function(name,sex,age){
 this.name = name;
 this.sex = sex;
 this.age = age;
};
//undefined

var p1 = new createPerson('z1',19,'男');
//undefined
p1.constructor
//输出
function (name,sex,age){
 this.name = name;
 this.sex = sex;
 this.age = age;
}
p1.constructor == createPerson
//输出:true

createPerson.constructor
//Function() { [native code] } //createPerson构造函数为Function,从一个侧面说明function也是对象


------------------------------------------------------------------------------------------------------------------------
7.js ==与 ===的区别

一个等号是赋值操作,==先转换类型再比较,进行值的对比。
而===先判断类型,如果不是同一类型直接为false,只有类型和值全部都相等,才相等。
------------------------------------------------------------------------------------------------------------------------
8.JS中一切皆对象
JS中基本数据类型,也存在着对象封装,比如下面数字123的构造函数是Number,test的构造函数是String,包含length的属性
(123).constructor
//输出:function Number() { [native code] }

'test'.constructor
//输出:String() { [native code] }
'test'.length;
//输出:4

//扩展Number的函数
Number.prototype.toString = function(){
	alert('hi,I\'m a number ');
};
(123).toString();
//输出:hi,I\'m a number 
Number.prototype
Number {toString: null, [[PrimitiveValue]]: 0}
------------------------------------------------------------------------------------------------------------------------
9.prototype原型

每个对象都连接到一个原型对象,并且可以从中继承属性。所有通过{}或者构造函数创建的对象都连接到Object{}
对象通过(对象名称.__proto__)可以查看原型
或者通过(对象名称.constructor.prototype)查看原型


var createPerson = function(name,sex,age){
 this.name = name;
 this.sex = sex;
 this.age = age;
};

var p1 = new createPerson('z1',19,'男');

p1.constructor
//输出:
fucntion(name,sex,age){
 this.name = name;
 this.sex = sex;
 this.age = age;
}
p1.constructor.prototype
//输出:
Object {}
createPerson.prototype
//输出:
Object {}

p1.constructor.prototype === createPerson.prototype
true



var p2 = {sex:'男'};

p2.constructor.prototype
//输出:Object {}


/*
在javascript中,创建一个新对象时,可以选择某个对象作为它的原型,比如
*/

var person = {name:'z3',age:18,sex:'男'};
Object.create = function(o){
	var F = function(){};
	F.prototype = o ;
	return new F();
};

var anotherPerson = Object.create(person);
anotherPerson.name;//z3
//对原型对象进行更新,发现已创建的对象值也随着变化
person.name = 'z4';
"z4"
anotherPerson.name
//输出:"z4"

//但当对象增加相同的属性后,原型对象的属性变化,不影响对象的属性值。因为对象读取值首先读取本身对象的值,后读取原型的值
anotherPerson.name = 'z5';

person.name = 'z6';
//输出:"z6"
anotherPerson.name
//输出:"z5"

delete anotherPerson.name 
//输出:true
anotherPerson.name//输出对象本身的属性值,原型对象的属性值不会被删除,除非通过delete 原型对象.属性输出.
//输出:"z6"

delete person.name
//输出:true
anotherPerson.name
//输出:undefined

//原型连接什么时候起作用呢?只有在检索值的时候才被用到
//如果尝试者去获取对象的某个属性值,但该对象没有此属性名,那么JAVASCRIPT会尝试着从原型对象中获取属性值。
//如果原型对象也没有该属性值则再从它的原型找,直到该过程最后达到终点Object.prototype。Object
//如果想要的属性完全不存在于原型链中,那么结果就是undefined。

person.age = 18;
anotherPerson.age//显示什么?

//原型关系是一种动态的关系。如果添加一个新的属性到原型中,该属性会立即对所有基于该原型创建的对象可见。

anotherPerson.__proto__===person;//true
__proto__显示对象的原型链



//可以使用hasOwnProperty方法来判断对像是否含有某个属性,如果对象拥有独有的属性,则返回true
//这个方法不会去检查原型链

------------------------------------------------------------------------------------------------------------------
10. arguments

arguments 对象是函数内部的本地变量;arguments 已经不再是函数的属性了。
你可以在函数内部通过使用 arguments 对象来获取函数的所有参数。这个对象为传递给函数的每个参数建立一个条目,
条目的索引号从 0 开始。例如,如果一个函数有三个参数,你可以通过以下方式获取参数:

arguments[0]
arguments[1]
arguments[2]

参数也可以被重新赋值:
arguments[1] = 'new value';


arguments 对象并不是一个真正的Array。它类似于数组,但没有数组所特有的属性和方法,除了 length。
例如,它没有 pop 方法。不过可以将其转换成数组
------------------------------------------------------------------------------------------------------------------------
11.利用JS特性实现AOP
AOP就是面向切面编程,主要作用是把一些核心业务逻辑模块无关的功能抽离出来,这些跟业务逻辑无关的功能
 通常包括日志统计,安全控制,异常处理等。把这些功能抽离出来后,又通过动态织入的方式渗入到业务逻辑模块中

  在JAVA中,可以通过反射和动态代理机制来实现AOP。但对于javascript这种动态语言,AOP的实现更加简单
  
  在javascript中实现AOP,都是指把一个函数动态织入到另外一个函数中。我们可以通过扩展Function.prototype来做到这一点
*/

Function.prototype.before = function(beforefn){
	 var that = this ;
	 return function(){
		 beforefn.apply(this,arguments);
		 return that.apply(this,arguments);
	 };
};

Function.prototype.after = function(afterfn){
	 var that = this ;
	 return function(){
		 var ret =that.apply(this,arguments);
		 afterfn.apply(this,arguments);
		 return ret ;
	 };
};

var func = function(){
	console.log(2);
};
func = func.before(function(){
	console.log(1);
}).after(function(){
	console.log(3);
});
func();

var func1 = document.getElementById;
undefined
func1('nt-contents');
//报错信息如下, 是由于document.getElementById函数中的this指向为windows对象,而windows对象不存在这些变量。
VM245:1 Uncaught TypeError: Illegal invocation(…)


//写那么复杂主要是将this的指向还是定位到document上面

var getElementById1 = (function(func){
	return function(){
		return func.apply(document,arguments);
	}
})(document.getElementById);   

------------------------------------------------------------------------------------------------------------------------
12.利用JS特性实现一些有趣的Function
var getId = document.getElementById1; //返回 这个对象 function(){return func.apply(document,arguments);}
var div = getId('ntp-contents');//返回func.apply(document,arguments)的对象,arguments参数值div1,func执行闭包中的document.getElementById函数
alert(div.id);

//我们上节课讲到,怎么在一个内部函数中保持外层的this上下使用了一个变量that来保存外,还可以使用以下方法
Function.prototype.bind =function(context){
	var self = this ;
	return function(){
		alert(self);
		alert(context);
		return self.apply(context,arguments);
	}
};

var obj ={name : 'steven'};
var func = (function(){
	alert(this.name)
}).bind(obj);


var isType =function(type){
	return  function(obj){
		return  Object.prototype.toString.call(obj)==='[object '+type+']';
	};
};

var isString = isType('String');
isString('hello world');

var isArray = isType('Array');

isArray([2,3]);

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics