文章目录
- this
- 在全局作用域下this就是window
- 函数执行的时候,看前面是否有.如果有this就是.前面的,如果没有就是window(非严格模式下),在严格模式下(undefined)
- 给元素绑定事件的时候,当事件触发,函数执行的时候,里面的this就是当前点击元素
- 自执行函数中的this是window(非严格模式下),在严格模式下为undefined
- 回调函数,无论是严格模式还是非严格模式,他的this都是window
- 构造函数(类)中的this指的就是当前的实例
- 通过bind,call,apply可以改变this的指向
- `箭头函数中没有this`也没有arguments,但是`在箭头函数中用到this会向上级查找`
- 单例设计模式
- 工厂模式(函数封装)
- 构造函数
- 原型链查找:
this
在全局作用域下this就是window
console.log(this);//window
函数执行的时候,看前面是否有.如果有this就是.前面的,如果没有就是window(非严格模式下),在严格模式下(undefined)
//"use strict";严格模式,此时注释掉了
function fn(){
console.log(this);
}
var obj={
"name":"li",
fn:fn
}
obj.fn();//{ name: 'li', fn: [Function: fn] }
fn();//window 如果是严格模式就是undefined
给元素绑定事件的时候,当事件触发,函数执行的时候,里面的this就是当前点击元素
ele.onclick=function(){
console.log(this);//当前点击的元素
}
自执行函数中的this是window(非严格模式下),在严格模式下为undefined
(function(){
console.log(this);//非严格模式下为window,严格模式下为undefined
})()
回调函数,无论是严格模式还是非严格模式,他的this都是window
"use strict"
setTimeout(function(){console.log(this);},1000);//window
什么是回调函数?
把一个函数当成一个参数传给另一个函数,例如:
"use scrict"
function fn(callback){
console.log(this);//undefined
callback();
}
fn(function(){console.log(this)});//undefined
//严格模式下是undefined 非严格是window*2
构造函数(类)中的this指的就是当前的实例
function fn(name){
this.name=name;
}
var f1=new fn("1");//{name:"1"}
var f2=new fn("2");//{name:"2"}
console.log(f1,f2,fn);//{name:"1"} {name:"2"} fn(name){this.name:name;}
通过bind,call,apply可以改变this的指向
function fn(){
console.log(this);
}
var obj={
name:"li",
fn:fn
}
fn.call(obj);//{ name: 'li', fn: [Function: fn] }
fn.apply(obj);//{ name: 'li', fn: [Function: fn] }
箭头函数中没有this
也没有arguments,但是在箭头函数中用到this会向上级查找
demo练习
var num=10;
var obj={num:20};
obj.fn=(function(num){
this.num=num*3;
num++;
return function(n){
this.num+=n;
num++;
console.log(num);
}
})(obj.num);
var fn=obj.fn;
fn(5);//22 这里的this是window
obj.fn(10);//23 这里的this是obj
console.log(num,obj.num)//65 30
单例设计模式
单例模式:可以把描述一个事物的所有属性放到一个对象中,这样避免了相互的干扰,这种设计模式就是单例设计
var obj1={
name:"cui",
sex:"男"
}
var obj2={
name:"yang",
sex:"男"
}
高级单例模式
var utils=(function(){
函数.........
return {
name:"yang",
sex:"男"
}
})()
utils.name;
工厂模式(函数封装)
将一个重复执行的事,封装成一个函数
function person (name,age,sex){
return {
name:name,
age:age,
sex:sex
}
}
var p1=person("李",12,"男");
var p1=person("王",18,"女");
构造函数
当函数执行的时候,前面一旦加了new,就变成了构造函数(类)
f1,f2变成了实例,实例是对象数据类型
如果函数执行的时候没有形参,可以把()省去
实例和实例是不相等的,空间地址不同
在构造函数中,通过this添加的属性名和属性值都是添加给了当前的实例,且都是私有的,构造函数中的this就是当前实例,
function fn(){
return 1;
}
var f1=new fn();
var f2=new fn();
console.log(f1,f2,fn);
构造函数执行的过程
- 形成一个私有作用域
- 形参赋值
- 变量提升
独有的,开辟一个堆内存,并且把函数里面的this指向这个堆内存(隐形的)
- 代码自上而下执行
把这个对象return返回(隐形的)
构造函数中的return
构造函数中一般情况下不要写return,如果写了,注意:
- 如果return基本数据类型就不会覆盖原来的
- 如果return引用数据类型,实例的结果就会改变为手动return的那个引用数据类型
- 如果只写return,那么不会覆盖原来的
function fn(name){
this.name=name;
}
var f1=new fn("li");
console.log(f1)//{name:"li"}
function fn(name){
this.name=name;
return {age:18}
}
var f1=new fn("li");
console.log(f1)//{age:18}
function fn(name){
this.name=name;
return 1;
}
var f1=new fn("li");
console.log(f1)//{name:"li"}
function fn(name){
this.name=name;
return
}
var f1=new fn("li");
console.log(f1)//{name:"li"}
判断是否属于一个类
用法:实例 instanceof 类
返回结果:布尔数据类型,true就属于,false不属于
function fn(){
return 1;
}
var f1=new fn();
console.log(f1 instanceof fn);//true
判断某个对象是否拥有某个属性in
用法:属性名 in 对象名
结果:布尔
检测某个属性是不是对象私有的hasOwnProperty
用法: 对象.hasOwnProperty(“属性名”)
返回值:布尔,不是私有的或者属性不存在都为false,是私有的就是true
function Fn(name,age){
this.name=name;
this.age=age;
}
var f1=new Fn("lili",18);
f1.hasOwnProperty("name");// true
f1.hasOwnProperty("toString");//fasle
创建数组的两种方式及注意事项
使用构造函数时,new Array()里的值如果有1个就是数组的长度(且每个项都为empty空的),如果有多个就是数组的每个项
var ary1=[1,2,3];
var ary2=Array(1,2,3);
var ary3=Array(5);
console.log(ary1,ary2,ary3)//[ 1, 2, 3 ] [ 1, 2, 3 ] [emptyx5]
js创建值的两种方式
- 字面量方式:var obj={}
- 基于构造函数: var obj2=new Object()
- 不管是哪种形式创建的,这些对象都是Object的一个实例。
注意:基本数据类型用字面量方式创建的实例,不是标准的实例,用instanceof检测为false,但是可以调用类的方法,如果用构造函数创建类,用instanceof检测为true
注意:引用数据类型,两种方式创建都可以被instanceof检测为true
var n1=1;
var n2=new Number(1);
console.log(typeof n1);//"number"
console.log(typeof n2);//"object"
n1.toFixed(2);//"1.00"
n2.toFixed(2);//"1.00"
原型和原型链
【函数数据类型】
:- 普通函数、构造函数、箭头函数
【对象】
:- 普通的对象、数组、时间对象、正则…
- prototype/_ _ proto _ _原型属性值也是对象,但不包含(function.prototype)
- 实例(不包括7种原始数据类型)
- 如10是Number的实例,但不是一个对象
- 大部分函数(重点是构造函数)都有一个属性prototype
(是原型,也可称为显式原型)
,他是属性是一个对象数据类型
,浏览器会默认给他开辟一个堆内存
,存的是公有的属性属性和方法
,供当前类所属实例调用- 箭头函数没有prototype属性
- prototype天生自带一个属性constructor,指的是当前的构造函数
(所属的类)
- 所有对象都天生自带一个_ _ proto _ _属性,他指向当前实例所属的原型,
找到最后时,__ proto__为null
原型链查找:
先看自己私有的有没有,如果没有,基于
__proto__
向上查找,(简单概括为先找私有,再看公有)
如果一直没找到就为undefined
function Fn(){
var n=100;
this.A=function(){console.log("私有A")};
this.B=function(){console.log("私有B")}
}
Fn.prototype.A=function(){console.log("公有A")};
var f1=new Fn();
var f2=new Fn();
console.log(f1.A==f2.A);
console.log(f1.__proto__.A==f2.__proto__.A);
console.log(f1.__proto__.A==Fn.prototype.A)
图解