-----------------------------------------------js语言---------------------------------------------------------
一种面向对象语言需要向开发者提供四种基本能力:
- 封装:把相关的信息(无论数据或方法)存储在对象中的能力
- 聚集:把一个对象存储在另一个对象内的能力
- 继承:由另一个类(或多个类)得来类的属性和方法的能力
- 多态:编写能以多种方法运行的函数或方法的能力
由于ECMAScript支持这些要求,因此可被是看做面向对象的。
在ECMAScript中,不能访问对象的物理表示,只能访问对象的引用。
每次创建对象,存储在变量中的都是该对象的引用,而不是对象本身。
因此JavaScript是基于面向对象的一种弱类型的网页脚本语言。
-----------------------------------------------细节---------------------------------------------------------------
算法永远比代码运行得快
- ~~()算法取整
- math.floor()代码取整
= = = 和 = =
= = = 是对比内容同时对比内存和数据类型(字符串、数字、布尔、数组、对象、Null、Undefined)
= = 只对比内容
- 1 = = = “ 1 ” // flase
- 1 = = “ 1 ” // true
---------------------------------------------------grid布局-----------------------------------------------------------
http://www.css88.com/archives/8675
--------------------------------------------------删除节点-------------------------------------------------------------------
在js,css里节点是不能自杀的;
display:none;是不在文档流中占位,该标签还存在,产生reflow和repaint(回流与重绘),会让页面崩塌
并且旗下所有子元素都会消失,株连性
visibility: hidden;还在文档中,可以看成透明度为0的不可点击空白,不会让页面崩塌
并且旗下所有子元素都会消失,但可以通过visibity:visible召唤回来
真正的删除标签,通过js,this.parentNode.removeChild(this);
-------------------------------------------------回流重绘-----------------------------------------------------------------------
http://www.css88.com/archives/4996
看这个网址很详细
当render tree中的一些元素需要更新属性,而这些属性只是影响元素的外观,风格,而不会影响布局的,比如background-color。则就叫称为重绘。
注意:回流必将引起重绘,而重绘不一定会引起回流。
哪些因素会导致回流?
1、调整窗口的大小;
2、改变字体,如果用rem 设置了根目录的字体大小,这样就减少了回流的次数;
3、增加或者移除样式表;
4、内容的变化,用户在input中输入了文字(这是不可避免的);
5、激活CSS的伪类;
6、操作class属性;
7、基本操作DOM(包括js中的domcument等);
8、计算offsetWidth与offsetHeight 属性,获取元素在窗口中的位置;
9、在html代码中直接设置style 属性的值,这个降低了代码的利用率,还影响性能。
如何避免回流?
1、如果想设定元素的样式,直接改变class名,而不是改变class中的某个特定的属性,比如height,weight;
2、避免设置多项内联样式,就是说少使用style;
3、应用元素动画的时候,使用属性的position属性的fixed值或absolute值;
4、避免使用table布局;
5、尽量在DOM树的最末端改变class,改变子节点的样式。
--------------------------------------------------块级作用域----------------------------------------------------
if 和 for 是没有块级作用域的,在里面var的 i 在外面也会影响的,污染全局变量,所以最好不用
最好用算法,三元运算符,递归,迭代去代替 if 和 for
也可以 function
-----------------------------------------------污染全局变量------------------------------------------------------
- 全局作用域
- 局部作用域(也叫本地作用域)
如果变量在函数之外定义,则变量处于全局作用域内。
在js中,最大是window,随便var一个变量等于整个window都能使用它
当你定义一个var $ = 0;为全局变量时,引入的 jq 里的 $ 就会崩溃调
不利于插件的使用,不利于别人的修改,所以最好在整个js外面包一个 var a = function(){ }
这样里面的全局变量全部会变成 a函数的局部变量
--------------------------------------------函数,对象,方法,属性-------------------------------------------------------------------
"属性"(property)和"方法"(method),object(对象),function(函数)
https://blog.csdn.net/u012767263/article/details/17002129 这个讲的很清楚
JavaScript语言是一门面向对象的语言,但是JavaScript中并没有类的概念的。于是JavaScript采用构造函数的方式来模拟类的效果
js 构造函数 就是 var 人 = function(){ } 等同于 function 人(){ }
function就是函数的意思,如同数组就是 Array
构造函数的特点:
a:构造函数的首字母必须大写,用来区分于普通函数
b:内部使用的this对象,来指向即将要生成的实例对象
c:使用New来生成实例对象
JavaScript 中每个函数都都表示为一个函数对象(函数实例),既然是对象,就有相关的属性和方法;
window就是一个对象,而且是最大的对象
new一个对象和不用new的区别
- 直接调用的时候它叫“普通函数”,此时用全局对象window做上下文。
- 用new操作符调用的时候它叫“构造函数”,此时用这个新生的对象做上下文。
- 用某个对象拽着它调用的时候,它叫做“方法”,此时用拽它的那个对象做上下文。
---------------------------------------------作用域(scope) 和 上下文(context)------------------------------------------
作用域是代码的使用范围
http://www.css88.com/archives/7255
http://focus2008.iteye.com/blog/2163504
https://www.cnblogs.com/myyouthlife/p/5179731.html
函数作用域跟块级作用域的区别是什么呢?
函数作用域:变量在定义的函数内及嵌套的子函数内处处可见;
块级函数域:变量在离开定义的块级代码后马上被回收。
JS中作用域有:全局作用域、函数作用域。没有块作用域的概念。
ECMAScript 6(简称ES6)中新增了块级作用域。
块作用域由 { } 包括,if语句和for语句里面的{ }也属于块作用域。
- 在函数作用域里定义的局部变量外部是访问不到的
- if和for在别的语言里是块级作用域,js没有块级作用域,
- 所以在if和for里定义的变量外部是可以访问,防止污染,应该把if和for写在function里隔离起来
而上下文(context)是用来指定代码某些特定部分中 this
的值。
这个函数的上下文是谁?问的就是这个函数的this是谁
---------------------------------------------闭包----------------------------------------------------------
一个函数有权访问另一个函数作用域中的变量,即在一个函数内部创建另一个函数
闭包就是跨作用域访问变量;
闭包的显著特点:
- 函数套函数,所以至少有两层函数。
- 外层函数最少要干三件事:
- 提供至少一个局部变量,注意,我没有说“定义变量”,因为变量除了定义,还有一种情况是通过参数传递进来,不需要定义。这个变量在外层函数执行完毕之后不能被销毁,销毁就不叫闭包。
- 定义至少一个内层函数。
- 想办法将内层函数返回给调用外层函数的作用域里的变量或者函数。通常是用
return
。 - 内层函数至少要干一件事:定义真正的执行语句。用的时候用内层函数。
闭包的技术原理就是利用作用域链是单向的这一特征。
那么闭包到底有个毛用呢?写简单易懂的代码会死么?闭包的三个好处:
1.希望一个变量长期驻扎在内存中
2.避免全局变量的污染
3.私有成员的存在
一个函数即使在词法作用域之外执行,也依然能记住并且能访问自己的词法作用域,这种用法就叫做闭包。
例子1
- var Foo = function(){
- var name = ‘fooname‘;
- var age = 12;
- this.getName = function(){
- return name;
- };
- this.getAge = function(){
- return age;
- };
- };
- var foo = new Foo();
- foo.name; // => undefined
- foo.age; // => undefined
- foo.getName(); // => ‘fooname‘
- foo.getAge(); // => 12
例子2
- function foo(x) {
- var tmp = 3;
- return function (y) {
- alert(x + y + (++tmp));
- }
- }
- var bar = foo(2);
- bar(10);
数据保留加外部调用就是闭包
自执行计时器闭包
function
newClosure() {
for
(
var
i = 0; i < 5; i++) {
(
function
(e) {
setTimeout(
function
() {
console.log(e);
})
})(i)
}
}
newClosure();
// 0 1 2 3 4
定时器闭包
function
log(i) {
return
function
() {
console.log(i);
}
}
function
newClosure() {
for
(
var
i = 0; i < 5; i++) {
setTimeout(log(i));
}
}
newClosure();
// 0 1 2 3 4
闭包保留作用域的例子
- function foo(){
- var a = 10;
- return function(){
- a *= 2;
- console.log(a);
- } }
- var fn = foo();
- fn(); // 20
- fn(); // 40
userName = null // 销毁闭包,释放内存
--------------------------------------------this和arguments---------------------------------------------------------
在js中,所有的函数再被调用的时候都会默认传入两个参数,一个是this,还有一个是arguments
- function aa(a,b){
- console.log(a*b);
- console.log( arguments[2]+arguments[3] );
- console.log("asd");
- }
- aa(1,2,3,4);
this指向使用他的最后一个对象
function
fn() {
console.log(
this
.a );
}
var
obj2 = {
a: 42,
fn: fn
};
var
obj1 = {
a: 2,
obj2: obj2
};
obj1.obj2.fn();
// 42 -- this引用的是obj2.
没有即使使用,让window执行,this指向window
function
fn() {
console.log(
this
.a );
}
var
obj = {
a: 2,
fn: fn
};
var
bar = obj.fn;
// 函数引用传递
var
a =
"全局"
;
// 定义全局变量
bar();
// "全局"
--------------------------------------------------回调函数---------------------------------------------------------------
函数A作为参数(函数引用)传递到另一个函数B中,并且这个函数B执行函数A。
我们就说函数A叫做回调函数。如果没有名称(函数表达式),就叫做匿名回调函数。
回调函数中可以通过闭包来访问外部的变量;
--------------------------------------------------函数重载---------------------------------------------------------------------
函数重载就是根据参数数量的多少执行函数里的不同功能事件
面向对象语言如Java的一个常见特性是:能够根据传入的不同数量量或类型的参数,通过“重载”函数来发挥不同的功用。
但是这个特性在Javascript中并没有被直接支持,可是有很多办法实现这一功能。
javascript不支持函数重载,不能够定义同样的函数然后通过编译器去根据不同的参数执行不同的函数。
js里不能建立同个名字的函数,得通过验证arguments的数量来实现
不管何种面向对象语,函数重载必须依赖两件事情,分别是:
1)判断传入参数数量的能力
2)判断传入参数类型的能力
-----------------------------------------------函数原型和原型链--------------------------------------------------------------------
Java/C++的面向对象是object - class
的关系,而JS是object - object
的关系,中间通过原型prototype连接,父类和子类形成一条原型链。
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_encapsulation.html
Function.prototype,共有属性,节省内存
下面两句话也很重要
1、每一个函数对象都有一个prototype属性,但是普通对象是没有的;
prototype下面又有个construetor,指向这个函数。
2、每个对象都有一个名为_proto_的内部属性,指向它所对应的构造函数的原型对象,原型链基于_proto_;
Person.prototype.constructor == Person;
person1.__proto__ == Person.prototype;
person1.constructor == Person;
所有对象的 __proto__ 都指向其构造器的 prototype;
function Person(name) {
this.name = name;
}var p = new Person(‘jack‘);
console.log(p.__proto__ === Person.prototype); // true
- var A = function(){};
- var a = new A();
console.log(a.__proto__); //A {}(即构造器function A 的原型对象) - console.log(a.__proto__.__proto__); //Object {}(即构造器function Object 的原型对象)
- console.log(a.__proto__.__proto__.__proto__); //null
- two.prototype.name = "two";
- two
.prototype.sayHello = function() {
console.log(this.name);
} - 等同于 two.prototype = {
- name: two ,
- sayHello : function() { console.log(this.name);}
- } //但是这么写等于重置了two.prototype,之前的所有prototype属性都会被清空
function two(){ } //函数对象
three = { } //普通对象
- var cat = function(name){ //构造一个有pro的函数
- this.name = name;
- this.prototype.sound = ”喵喵喵“; //不能这么写,必须把this改成函数名
- cat.prototype.sound = ”喵喵喵“;
- }
- var one = new cat(‘小毛‘);
- console.log(one);
- console.log(JSON.stringify(one)); //可以发现pro属性是不会被存入json的,因为pro属性不会被序列化
------------------------------------------------call,apply,bind-----------------------------------------------------------------------------
https://www.cnblogs.com/libin-1/p/6069031.html
所以根据原型的规则,所有的函数都可以使用原型中属性和方法,所以来说,对于所有的函数都可以使用call,apply和bind方法。
https://www.cnblogs.com/libin-1/p/5823025.html
call
、apply
和bind
是Function
对象自带的三个方法,这三个方法的主要作用是改变函数中的this
指向。
有什么作用?
我认为它们的作用可以用一句话来描述:就是改变this的指向。
call,apply和bind的区别
它们在功能上是没有区别的,都是改变this的指向,它们的区别主要是在于方法的实现形式和参数传递上的不同
①:函数.call(对象,arg1,arg2....)
②:函数.apply(对象,[arg1,arg2,...])
③:var ss=函数.bind(对象,arg1,arg2,....)
例子1:
- function show(sex){
- console.log("普通函数"+sex);
- }
- var person={
- name:"aa",
- age:14
- };
- show.call(person,"男");
- show.apply(person,["女"]);
- //对于bind来说,用法更加的灵活 ,bind是被动执行的
- var ss=show.bind(person,"不明");
- ss();
function.call();
function.apply();
括号里面填什么,什么就是function的this,每天就是默认原this:
例子2:
https://blog.csdn.net/myhahaxiao/article/details/6952321
/*定义一个人类*/
- function Person(name,age)
- {
- this.name=name;
- this.age=age;
- }
- /*定义一个学生类*/
- functionStudent(name,age,grade)
- {
- Person.apply(this,arguments);
- /*在Studen函数里面可以将apply中修改成如下:Person.call(this,name,age);*/
- this.grade=grade;
- }
- //创建一个学生类
- var student=new Student("zhangsan",21,"一年级");
- //测试
- alert("name:"+student.name+"\n"+"age:"+student.age+"\n"+"grade:"+student.grade);
//大家可以看到测试结果name:zhangsan age:21 grade:一年级
//学生类里面我没有给name和age属性赋值啊,为什么又存在这两个属性的值呢,这个就是apply的神奇之处.
什么情况下用apply,什么情况下用call
在给对象参数的情况下,如果参数的形式是数组的时候,比如apply示例里面传递了参数arguments,
这个参数是数组类型,并且在调用Person的时候参数的列表是对应一致的(也就是Person和Student的参数列表前两位是一致的) 就可以采用 apply ,
如果我的Person的参数列表是这样的(age,name),而Student的参数列表是(name,age,grade),这样就可以用call来实现了,
也就是直接指定参数列表对应值的位置(Person.call(this,age,name,grade));
-----------------------------------------------封装---------------------------------------------------------------------
例子:https://www.netnr.com/jz/index
例子:https://blog.csdn.net/sinat_36146776/article/details/52923465
讲解:http://www.php.cn/js-tutorial-387538.html
把一个函数事件包装起来多次使用就是封装
最简单的封装就是函数对象
- function dog(name,color){
- this.name=name;
- this.color=color;
- }
封装插件的基础格式
- (function(window){
- var aa=function(){
- alert(arguments [ 0 ]);
- }
- //定义$来代表这个插件
- window.$ = aa;
- })(window);
- //执行
- $(123); //把 alert 函数封装成 $
-----------------------------------------------函数继承-----------------------------------------------------------------
构造函数的继承
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance.html
非构造函数的继承
http://www.ruanyifeng.com/blog/2010/05/object-oriented_javascript_inheritance_continued.html
---------------------------------------------------json---------------------------------------------------------------
- json对象 { " 健 " : " 值 "," 健" : [ " 健 " : " 值 " , " 健 " : " 值 " ] }
- json数组 [ { 可以是对象 } , { 也可以是josn对象 } ]
- json字符串 ‘ { json对象 } ‘
json和对象object的区别是键值由 “ ” 包着
访问json数组可以用 for in
json有保存性,对象没有
对象用使用能力,json没有
所以要用相互转化,转化就是 序列化 和 反序列化
反序列化:把对象转化成json储存
- json.stringify(json , [ " 可选属性可以填上单独提取的键 " ],"+空格的话生成的对象有换行");
- var s = { name : " 小毛 " , age : 12 , 性别 : " 男 " }
- var a = JSON.stringify( s , [ " age " ] , " ");
- 虽然对象可以有函数方法,日期,undefined等属性,但是json是不支持的,所以会直接被无视,日期可以用tojson转成字符串格式再存入json
序列化:把json序列化成对象
- var s = ‘ { " name " : " 小毛 " , " age " : " 12 " , " 性别 " : " 男 " } ‘; 两端要加单引号把json对象变成json字符串
- var a = JSON.parse(s); parse只能转化json字符串格式
------------------------------------------------for,if----------------------------------------------------------------------------
----------------------------------------------数组arr------------------------------------------------------------------------
数组排序:https://www.cnblogs.com/real-me/p/7103375.html
数组的操作:https://www.cnblogs.com/obel/p/7016414.html
数组和对象:http://www.jb51.net/article/75845.htm
数组和字符串的操作:https://www.cnblogs.com/-biubiu/archive/2016/01/08/js-common-function.html
- var key = ‘ ‘; //建立对象
- var value = obj[key]; 把对象放进数组
- 遍历Array的时间复杂度是O(n),而遍历Object的时间复杂度是O(1)
- 把100个Unique的字符mapping到1000个字符串数组上,耗时25-30s!
- 后来把for遍历改成了Object模拟的集合的成员引用,同样的数据量mapping,耗时仅1.7-2s!!!
- 对于集合的遍历效率(从高到低):var value = obj[key]; > for ( ; ; ) > for ( in )。
- 效率最差的就是for( in )了,如果集合过大,尽量不要使用for ( in )遍历
-----------------------------------------------自执行函数-------------------------------------------------------
传参
- var a = 2;
- (function IIFE(global){
- var a = 3;
- console.log(a);//3
- console.log(global.a);//2
- })(window);
- console.log(a);//2
闭包
- var i = 1;
- var IFun = (function(){
- var i = 1;
- console.log(i);
- return function(){
- i++;
- console.log(i);
- } })();
- IFun();
- IFun();
最终输出的结果为1,2,3,很多会下意识的觉得结果会有4个值,
但是运用了return 返回值以及自执行函数将函数返回给IFun变量,
使得在第一次操作过程后,将返回函数直接赋给IFun。
--------------------------------------------------------------------------------------------------------------------------------
递归,迭代,自执行传参,es6
原文地址:https://www.cnblogs.com/pengdt/p/8659239.html