15-构造函数及原型

一.JSON

js中的对象只有js自己认识,其他语言是不认识的,如果需要数据通信怎么办,我们发现至少所有语言都认识数字,字符串,布尔值,所以我们可以将js对象转成字符串

JSON就是一个特殊格式的字符串,这个字符串可以被任意的语言所识别

并且可以转换为任意语言中的对象,JSON在开发中主要用来数据交互

1. JSON
  1. JSON ==> JavaScript Object Notation JS对象表示法

  2. JSONjs对象的格式一样,只不过JSON字符串中的属性名必须加双引号

    var json = '{"name":"wuwei","age":18}'
    
2. JSON的分类
  1. 对象 {}

    var obj = '{"name":"wuwei","age":18}'
    // 这叫`JSON`对象
    
  2. 数组 []

    var arr = '[1,2,3,"hello",true]';
    // 这叫`JSON`数组
    
3. JSON中允许的值
  1. 字符串
  2. 数值
  3. 布尔值
  4. null
  5. 对象(只能是普通对象,不能是函数)
  6. 数组
4. JSON的方法(也叫序列化对象)

js中,给我们提供了一个工具类,就叫JSON

这个对象可以帮助我们将一个JSON转换位JS对象,也可以将一个JS对象转换为一个JSON

4.1 将JSON字符串转成js对象

JSON.parse(json)

var json = '{"name":"wuwei","age":18}';
var o = JSON.parse(json);
console.log(o);  // {name: "wuwei", age: 18}
4.2 将js对象转换为JSON对象

JSON.stringify(obj)

var obj = {name:"wuwei",age:18};
var json = JSON.stringify(obj);
console.log(json); // '{"name":"wuwei","age":18}'
5. 兼容

JSON对象在IE 7 及以下,不兼容,会报错JSON未定义

IE 7 及以下兼容

使用eval ()函数,

这个函数可以用来执行一段字符串形式的JS代码,并将结果返回

如果使用eval()执行的字符串中含有{},{}会被当成代码块

如果不希望{}被当成代码块,则需要在字符串前后各加一个()

var json = '{"name":"wuwei","age":18}';
var obj = eval("("+json+")");
console.log(obj);  // {name: "wuwei", age: 18}

在开发中尽量不要使用,因为eval()性能比较低,同时具有安全性问题

如果真的需要兼容IE 7及以下可以引入外部封装json的js文件解决

二. 对象复习

1. 对象的创建
1.1. 字面量方式(也叫直接量)
var obj = {}; 
1.2 new操作符创建对象
var obj = new Object()
2.对象属性和方法
2.1 对象的属性

对象有属性,所谓的属性就是这个对象的特点、特性

var student = {};
student.sex = '男孩'

2.2 对象的方法

对象只能有属性,只是如果这个属性的值是一个函数,那么这个函数我们就称为对象的“方法”(method)。

student.study = function(){
    console.log('我学会了语文')
}

三. 构造函数

1. 构造函数的原理

JavaScript规定,一个函数可以用new关键字来调用。那么此时将按顺序发生四件事情:

1)隐秘的创建一个新的空对象

2)将这个函数里面的this绑定到刚才创建隐秘新对象上

3)执行函数体里面的语句

4)返回这个新的对象

例子:

function People(){
    this.name = "小明";
    this.age = 18;
    this.sex = "男";	
}
// 使用new关键字来调用函数,那么函数就叫做构造函数,将返回一个对象
var xiaoming = new People();

console.log(xiaoming);  // People {name: "小明", age: 18, sex: "男"}
console.log(xiaoming.age);  //18

好了,也就是说,我们现在学习了函数的new的调用方式:使用new关键字来调用。

厉害了,现在我们发现函数不仅仅能够执行,还能返回出来一个对象。也就是说,对象是函数“生”出来的,对象是函数“new”出来的。

所以我们称呼这个生出对象的函数,叫做构造函数,一般的,构造函数用大写字母开头。也叫作People“类”。

我们称呼xiaoming这个对象是People类的实例。

2. 构造函数类和实例

Person这个函数将被new关键词来调用,所以称为构造函数

我们说,这些返回的对象都有形同的属性群,所以可以看做是一类东西,那么People这个构造函数,也就可以看成类的定义

例子:

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

//new关键字造出来的xiaoming、xiaohong,我们称为People类的实例。可以理解为实体
var xiaoming = new People("小明",20,"男");
var xiaohong = new People("小红",16,"女");

console.log(xiaoming);
console.log(xiaohong);

但是但是JavaScript中,没有类的概念。是通过构造函数的4步走机制来创建类似的对象,可以看为类。JS这个语言是“基于对象”(base Object)的语言,不能叫做“面向对象”(orinted object)的语言。

所以我们的构造函数,也可以看成类的定义:

构造函数其实就是一个普通的函数,JS没有规定函数里写什么,。只不过我们知道new操作符的原理后,就习惯了先用this.’…’ = 来罗列所有属性,然后罗列所有的方法而已。你一定要深刻理解:

new调用一个函数的时候,函数里面的语句会执行。

function People(name,age,sex){
    this.name = name;
    this.age = age;
    this.sex = sex;
    this.sayHello = function(){
        alert("你好我是" + this.name + ",nice to meet you");
    }
}

function Dog(name,pinzhong,age,sex){
    this.name = name;
    this.pinzhong = pinzhong;
    this.age = age;
    this.sex = sex;
    this.wangwang = function(){
        alert("汪汪汪汪" + this.name + "汪汪汪汪汪汪");
    }
}

var wuwei = new People("wuwei",11,"男");
xiaoming.sayHello();

var xiaobai = new Dog("小白","京巴",2,"公的");
xiaobai.wangwang();

3. 构造函数里面的注意事项
3.1 如果构造函数里没有this,那么将创建一个空对象
//构造函数里面如果没有了this,那么就废了,就不能给隐秘新创建出来的对象添加属性。但是里面的语句能够执行!!所以new出来的就是一个空对象
function People(){
    for(var i = 1 , sum = 0; i <= 100 ; i++){
        sum += i;
    }
    alert(sum);
}

var wuwei = new People();
console.log(xiaoming);

3.2 构造函数构造函数中,不允许出现return语句

出现return语句了,将不能返回新创建的那个对象,而是返回return 语句后面的内容

function People(name,age){
    this.name = name;
    this.age = age;
    return {"a":1,"b":2};
}

var wuwei = new People("wuwei",12);
console.log(wuwei);

3.3 JS没有规定构造函数中的语句的规范,想怎么写就怎么写:
// 这就是函数 你想怎么写就怎么写
function People(name,age){
    this.name = name;
    this.age = age;
    // if(this.age >= 18){
    // 	this.state = "成年人";
    // }else{
    // 	this.state = "未成年";
    // }

    this.state = this.age >= 18 ? "成年人" : "未成年";
}

var wuwei = new People("wuwei",11);
alert(wuwei.state);

总结一下

当一个函数用()调用的时候,this就是window

当一个函数用对象调用的时候,this就是这个对象

当一个函数绑定给一个HTML元素事件的时候,this就是这个HTML元素

当一个函数用定时器调用的时候,this就是window

当一个函数用apply、call调用的时候,this就是你指定这个东西

当一个函数用new调用的时候,this就是隐秘创建的空对象,函数里面的语句将被执行,并且返回新对象

面向对象,首先就两个词,构造函数和实例

面向对象就是一种组织代码的方式

四. 原型 prototype

1 原型 prototype

prototype就是英语“原型”的意思。原型是构造函数创建对象的原始模型

原型的特点:

原型也是对象,原型是函数对象的一个属性
原型自带constructor属性, constructor指定构造函数
构造函数创建出的对象会继承原型的属性和方法

// 任何函数都有原型,只是原型对于普通函数没什么大用,但对于构造函数用处极大
function fun(){
    console.log("您好")
}

console.log(fun.prototype);
console.log(typeof fun.prototype);

在JavaScript中,任何一个函数,都有一个prototype属性,指向一个对象。打印prototype属性,你会发现这个属性指向一个空对象。打印prototype的类型,发现是object类型。

2. 原型对象与实例

一个函数的原型,对于普通函数来说,没任何鸟用。但是如果函数是一个构造函数,那么函数的原型,用处极大!

示例:

function People(name,sex,age){
    this.name = name;
    this.sex = sex;
    this.age = age;
}
People.prototype = {
    hight: 180
}

var wuwei = new People("wuwei","男",18);

console.log(wuwei.name);  // "wuwei"
console.log(wuwei.sex);   // "男"
console.log(wuwei.age);   // 18
console.log(wuwei.hight); // 180

所以我们甚至可以把所有的属性都加在原型上

// 构造函数
function People(){
}

//构造函数的原型,我们更改了构造函数的原型,为一个新的对象:
People.prototype = {
    name : "wuwei",
    sex : "男",
    age : 18,
    hight: 180
}
var wuwei = new People();

console.log(wuwei.name);  // "小明"
console.log(wuwei.sex);   // "男"
console.log(wuwei.age);   // 18
console.log(wuwei.hight); // 180

当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,我们的感觉,构造函数的原型中,所有的属性也加给了这个对象

prototype一定是函数的属性,但这个函数是一个构造函数的时候,那么它new出来的对象,将以他的原型那个对象为new出来的实例的原型对象

3. 实例对象的__proto__ 属性

当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,也会把这个函数的__proto__指向构造函数的prototype。

// 构造函数
// 构造函数里面没有任何语句,也就是说,这个构造函数在执行的时候,不会给创建出来的对象添加任何属性。
function People(){
}

//构造函数的原型,我们更改了构造函数的原型,为一个新的对象:
People.prototype = {
    name : "wuwei",
    sex : "男",
    age : 18,
    hight: 180
}

//当一个对象被new出来的时候,不仅仅执行了构造函数里面的语句,也会把这个函数的__proto__指向构造函数的prototype。
var wuwei = new People();


//当我们试图访问sex、age属性的时候,身上没有。那么就去查找原型,原型身上有,就当做了自己的属性返回了。
console.log(wuwei.name);	
console.log(wuwei.sex); //自己没有,找原型对象
console.log(wuwei.age); //自己没有,找原型对象

console.log(wuwei.__proto__); 
// {name: "wuwei", sex: "男", age: 18, hight: 180}

console.log(wuwei.__proto__ == People.prototype);
// true

注意:

任何一个对象,都有__proto__属性,这个属性是Chrome自己的属性,别的浏览器不兼容,但是别的浏览器也有原型对象,只不过不能通过__proto__进行访问而已。

这是属性指向自己的原型对象。

4. 原型的扩展

我们的JavaScript有一个非常牛逼的机制:原型链查找。

当我们试图访问一个对象身上的属性的时候,如果这个对象身上有这个属性,则返回它的值。如果它身上没有这个属性,那么将访问它的原型对象,检测它的原型对象身上是否有这个值,如果有返回它原型对象身上的这个值。

也就是说,我们刚才讲解了2个对象和一个函数的故事。任何一个函数都有原型,原型是一个对象,用prototype来访问。

当这个函数是构造函数的时候,new出来的对象,它们的原型对象就是这个构造函数的原型。

prototype我们称为“原型”,只有函数有原型

__proto__我们称为“原型对象”,任何对象都有原型对象。

你可能感兴趣的:(笔记,javascript)