js 基础知识

数据类型

原始类型

ECMAScript 有 5 种原始类型(primitive type),即 Undefined、Null、Boolean、Number 和 String以及symbol(ES6)。

引用数据类型

对象(Object)、数组(Array)、函数(Function)

typeof 运算符
  1. undefined - 如果变量是 Undefined 类型的
  2. boolean - 如果变量是 Boolean 类型的
  3. number - 如果变量是 Number 类型的
  4. string - 如果变量是 String 类型的
  5. object - 如果变量是一种引用类型或 Null 类型的
instanceof

从原型的角度,来判断某引用属于哪个构造函数,从而判定它的数据类型。
可以判断数据类型,还可以在继承关系中用来判断一个实例是否属于它的父类型。

Object instanceof Object //true
Function instanceof Function //true
Function instanceof Object //true

判断是对象还是数组

//原理:
var a = [1,4,6]
var b = {a:1}
a instanceof Array //true
a instanceof Object //true
b instanceof Array //false
b instanceof Object //true
Array.isArray(a);//true
Array.isArray(b)//false

	 //判断是否为数组
    function isArray(obj) {
    	return obj instanceof Array;
    }

    //判断是否为对象(json对象)
    function isObject(obj) {
        if (!(obj instanceof Array) && (obj instanceof Object)) {
            return true;
        }
        return false;
    }

this

  1. 在全局环境中,this都是指向全局对象windows
  2. 在函数调用时,this指向取决于调用它的方式

script 标签

//脚本将会异步运行,HTML5新特性:
<script type="text/javascript" src="demo_async.js" async="async"></script>

//defer 属性规定是否对脚本执行进行延迟,直到页面加载为止,只有ie支持:
<script type="text/javascript" defer="defer">
alert(document.getElementById("p1").firstChild.nodeValue);
</script>

//定义外部脚本文件中所使用的字符编码:
<script type="text/javascript" src="myscripts.js" charset="UTF-8"></script>

在这里插入图片描述

replace()

replace() 方法用于在字符串中用一些字符替换另一些字符,或替换一个与正则表达式匹配的子串,该方法不改变字符串本身

var str = 'bob'
var rep = str.replace('b','a')
console.log(str)  //bob
console.log(rep) //aob

正则表达式对象或字面量(支持gi模式) g全局匹配 i忽略大小

var str = 'bob'
var rep = str.replace(/b/g,'a')
console.log(rep) //aoa

也可使用function做为第二个参数

name = 'aaa bbb ccc';
uw=name.replace(/\b\w+\b/g, function(word){
  return word.substring(0,1).toUpperCase()+word.substring(1);}
  );
//"Aaa Bbb Ccc"

call apply bind

call apply bind 都是改变 this 指向的,第一个参数都是this 要指向的对象,也就是要指定的上下文。
bind 是返回对应函数,便于稍后调用;apply 、call 则是立即调用 。

func.call(this, arg1, arg2);
func.apply(this, [arg1, arg2]);
func.bind(this, arg1, arg2)();

数组去重

function a (arr){
	return Array.from(new Set (arr));
}

原型原型链

var Person = function(){
        	this.old = '18' //实例成员
		}
Person.nn = 'cookie' //静态成员
Person.prototype.sing = function () {
        console.log('我爱唱歌);
    };
var person = new Person()
console.log(person.__proto__ === Person.prototype); //true
person.nn //undefined  实例无法访问静态成员
person.old//18
Person.old//undefined  通过构造函数无法直接访问实例成员
Person.nn //cookie 通过构造函数可直接访问静态成员

在这里插入图片描述
每一个构造函数都有它自己的对象,通过prototype指向它的原型对象。
此构造函数new出来的实例,通过_proto_指向构造函数的原型对象。

原型与原型层层相链接的过程即为原型链。
原型的作用,就是共享方法。
原型中this的指向是实例。

实例成员: 实例成员就是在构造函数内部,通过this添加的成员。实例成员只能通过实例化的对象来访问。

静态成员: 在构造函数本身上添加的成员,只能通过构造函数来访问

定义构造函数的规则:公共属性定义到构造函数里面,公共方法我们放到原型对象身上。

查找属性
  1. 首先在对象自身上查找是否有该属性,如果有,返回结果

  2. 如果没有,就去对象的原型上进行查找, 如果有,返回结果

  3. 如果没有,就沿着原型链继续往上查找,直到Object.prototype原型上即可,如果有,返回结果

  4. 如果Object.prototype原型上也没有,返回undefined

继承

  1. 原型链继承
function a() {
	this.name = 'hello'
    this.colors = ['red', 'green', 'blue']
}
function b() {
	this.old = '17'
}
b.prototype = new a();
var b1 = new b();
console.log(b1 instanceof a); //true
a.prototype.isPrototypeOf(b1); // true

b1.colors.push('black');
var b2 = new b();
b2.colors; // ["red", "green", "blue", "black"]

缺点:
1)有引用类型时,各个实例对该引用类型的操作会影响其它实例。
2)没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数。

  1. 借用构造函数继承
function a(){
    this.colors = ['red', 'green', 'blue']
}
function b(){
    a.call(this)
}
var b1 = new b();
b1.colors.push('black');
console.log(b1.colors); //["red", "green", "blue", "black"]
var b2 = new b();
console.log(b2.colors); //["red", "green", "blue"]
function a(name){
    this.colors = ['red', 'green', 'blue']
    this.name = name
}
function b(){
    a.call(this,'cookie')
}
var b1 = new b();
console.log(b1.name)

利用call或者apply把父类中通过this指定的属性和方法复制(借用)到子类创建的实例中。

优势:相对于原型链而言,借用构造函数有一个很大的优势,即可以在子类型构造函数中向超类型构造函数传递参数。因为属性是绑定到this上面的,所以调用的时候才赋到相应的实例中,各个实例的值就不会互相影响了。
有引用类型时,各个实例对该引用类型的操作不会影响其它实例。

缺点:如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

  1. 组合继承
    是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。
    思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。这样,既通过在原型上定义方法实现了函数复用,又能够保证每个实例都有它自己的属性。
function a(name) {
	this.name = name
    this.colors = ['red', 'green', 'blue']
}
a.prototype.sayName = function(){
    console.log(this.name)
}
function b(name, age){
	//继承属性
    a.call(this, name)
    this.age = age
}
//继承方法
b.prototype = new a();
b.prototype.constructor = b
b.prototype.sayAge = function(){
    console.log(this.age)
}

var b1 = new b('cookie', 18);
b1.colors.push('black');
console.log(b1.colors);//["red", "green", "blue", "black"]
b1.sayName();//'cookie'
b1.sayAge(); //18

var b2 = new b('frank', 19);
console.log(b2.colors);//["red", "green", "blue"]
b2.sayName();//'frank'
b2.sayAge(); //19

缺点:组合继承最大的问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。虽然子类型最终会包含超类型对象的全部实例属性,但我们不得不在调用子类型构造函数时重写这些属性。

  1. Class继承
    Class 可以通过extends关键字实现继承。子类必须在constructor方法中调用super方法,否则新建实例时会报错。这是因为子类自己的this对象,必须先通过父类的构造函数完成塑造,得到与父类同样的实例属性和方法,然后再对其进行加工,加上子类自己的实例属性和方法。如果不调用super方法,子类就得不到this对象。
class ColorPoint extends Point {
  constructor(x, y, color) {
    super(x, y); // 调用父类的constructor(x, y)
    this.color = color;
  }

  toString() {
    returnthis.color + ' ' + super.toString(); // 调用父类的toString()
  }
}

参考资料:https://mp.weixin.qq.com/s/psY8M9eMpWrZygHgfVYJCg

递归深拷贝

// 定义一个深拷贝函数  接收目标target参数
function deepClone(target) {
    // 定义一个变量
    let result;
    // 如果当前需要深拷贝的是一个对象的话
    if (typeof target === 'object') {
    // 如果是一个数组的话
        if (Array.isArray(target)) {
            result = []; // 将result赋值为一个数组,并且执行遍历
            for (let i in target) {
                // 递归克隆数组中的每一项
                result.push(deepClone(target[i]))
            }
         // 判断如果当前的值是null的话;直接赋值为null
        } else if(target===null) {
            result = null;
         // 判断如果当前的值是一个RegExp对象的话,直接赋值    
        } else if(target.constructor===RegExp){
            result = target;
        }else {
         // 否则是普通对象,直接for in循环,递归赋值对象的所有值
            result = {};
            for (let i in target) {
                result[i] = deepClone(target[i]);
            }
        }
     // 如果不是对象的话,就是基本数据类型,那么直接赋值
    } else {
        result = target;
    }
     // 返回最终结果
    return result;
}

遍历对象数组

对象

var obj = {a: 3, v: 4, g: 'p'}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值